Problema di rotta relativo agli Umlaut con codifica Url (usando il framework Zend)
-
02-07-2019 - |
Domanda
Oggi mi sono imbattuto in un problema che sembra essere un bug nello Zend-Framework. Dato il seguente percorso:
<test>
<route>citytest/:city</route>
<defaults>
<controller>result</controller>
<action>test</action>
</defaults>
<reqs>
<city>.+</city>
</reqs>
</test>
e tre URL:
- mysite.local / citytest / Berlino
- mysite.local / citytest / Amburgo
- mysite.local / citytest / M% FCnchen
l'ultimo URL non corrisponde e pertanto non viene chiamato il controller corretto. Qualcuno ha avuto un'idea del perché?
Fyi, dove sto usando Zend-Framework 1.0 (Sì, lo so che è antico ma non ho il compito di cambiarlo: - /)
Modifica: da quello che ho sentito, presto aggiorneremo a Zend 1.5.6, ma non so quando, quindi una patch sarebbe fantastica.
Modifica: l'ho rintracciato fino alla seguente riga (Zend / Controller / Router / Route.php: 170):
$regex = $this->_regexDelimiter . '^' .
$part['regex'] . '$' .
$this->_regexDelimiter . 'iu';
Se lo cambio in
$this->_regexDelimiter . 'i';
funziona. Da quello che ho capito, il modificatore u è per lavorare con personaggi asiatici. Dato che non li uso, sto bene con quella patch per sapere. Grazie per aver letto.
Soluzione
Il problema è il seguente:
L'uso del modificatore del modello / u impedisce parole dall'essere mutilato ma invece PCRE salta stringhe di caratteri con valori di codice maggiori di 127. Pertanto, \ w non corrisponderà a parola multibyte (ascii non inferiore) a all (ma ha anche vinto & # 8217; t restituisce porzioni di esso). Dalla pagina man pcrepattern;
In modalità UTF-8, caratteri con valori maggiore di 128 non corrisponde mai a \ d, \ s, o \ w e corrisponde sempre a \ D, \ S e \ W. Questo è vero anche quando Unicode il supporto della proprietà del personaggio è disponibili.
Da Gestione di UTF-8 con PHP . Pertanto è in realtà irrilevante se il tuo URL è codificato ISO-8859-1 (mysite.local / citytest / M% FCnchen) o UTF-8 codificato (mysite.local / citytest / M% C3% BCnchen), il regex predefinito non lo farà incontro.
Ho anche fatto esperimenti con le umlaut negli URL in Zend Framework e sono giunto alla conclusione che non vorresti davvero le umlaut nei tuoi URL. Il problema è che non puoi fare affidamento sulla codifica utilizzata dal browser per l'URL. Firefox (precedente alla 3.0) ad esempio UTF-8 non codifica gli URL immessi nella casella di testo dell'indirizzo (se non specificato in about: config) e IE ha una casella di controllo tra le sue opzioni per scegliere tra la codifica regolare e UTF-8 per i suoi URL . Ma se si fa clic sui collegamenti all'interno di una pagina, entrambi i browser utilizzano l'URL nella codifica specificata (UTF-8 su una pagina UTF-8). Pertanto, non puoi essere sicuro di quale codifica gli URL vengano inviati alla tua applicazione e rilevare la codifica utilizzata non è così banale da fare.
Forse è meglio usare i parametri traslitterati nei tuoi URL (es. modifica & # 196; in Ae e così via). C'è un modo davvero semplice per farlo (non so se funziona con tutte le lingue ma lo sto usando con stringhe tedesche e funziona abbastanza bene):
function createUrlFriendlyName($name) // $name must be an UTF-8 encoded string
{
$name=mb_convert_encoding(trim($name), 'HTML-ENTITIES', 'UTF-8');
$name=preg_replace(
array('/ß/', '/&(..)lig;/', '/&([aouAOU])uml;/', '/&(.)[^;]*;/', '/\W/'),
array('ss', '$1', '$1e', '$1', '-'),
$name);
$name=preg_replace('/-{2,}/', '-', $name);
return trim($name, '-');
}
Altri suggerimenti
Per favore, funziona perfettamente per me
/^[\p{L}-. ]*$/u
-
^
Inizio della stringa -
[ ... ]*
Zero o più dei seguenti: -
\p{L}
Caratteri lettera Unicode -
–
trattini -
.
punti - spazi
-
$
Fine della stringa -
/u
Abilita la modalità Unicode in PHP
Esempio:
$str= ‘Füße’;
if (!preg_match(“/^[\p{L}-. ]*$/u”, $str))
{
echo ‘error’;
}
else
{
echo “success”;
}
Il modificatore u fa sì che regexp si aspetti un input utf-8. Questo suggerirebbe che ZF prevede input codificato utf-8 e non ISO-8859-1 (non ho troppa familiarità con ZF, quindi sto solo indovinando qui).
In tal caso, dovrai codifica utf-8 il ü
prima usandolo in un URL. Diventerebbe quindi: mysite.local/citytest/M%C3%BCnchen
Nota che poiché il resto della tua applicazione probabilmente parla ISO-8859-1 (che è l'impostazione predefinita per PHP < = 5), dovrai decodificare esplicitamente la variabile con utf8_decode , prima di poterlo utilizzare.