Problema de ruta con diéresis codificadas en URL (usando el marco Zend)
-
02-07-2019 - |
Pregunta
Hoy me topé con un problema que parece ser un error en Zend-Framework.Dada la siguiente ruta:
<test>
<route>citytest/:city</route>
<defaults>
<controller>result</controller>
<action>test</action>
</defaults>
<reqs>
<city>.+</city>
</reqs>
</test>
y tres URL:
- mysite.local/citytest/Berlín
- mysite.local/citytest/Hamburgo
- mysite.local/citytest/M%FCnchen
la última URL no coincide y, por lo tanto, no se llama al controlador correcto.¿Alguien tiene una idea de por qué?
Para tu información, ¿dónde estás usando Zend-Framework 1.0 (Sí, sé que es antiguo pero no estoy a cargo de cambiarlo :-/)
Editar:Por lo que he oído, pronto actualizaremos a Zend 1.5.6, pero no sé cuándo, por lo que un parche sería genial.
Editar:Lo rastreé hasta la siguiente línea (Zend/Controller/Router/Route.php:170):
$regex = $this->_regexDelimiter . '^' .
$part['regex'] . '$' .
$this->_regexDelimiter . 'iu';
Si cambio eso a
$this->_regexDelimiter . 'i';
funciona.Por lo que tengo entendido, el modificador u es para trabajar con caracteres asiáticos.Como no los uso, me parece bien ese parche para saberlo.Gracias por leer.
Solución
El problema es el siguiente:
El uso del modificador del patrón /u evita que las palabras se destrozaran, pero en su lugar, PCRE omita las cadenas de caracteres con valores de código superiores a 127.Por lo tanto, W no coincidirá con una palabra multibyte (ASCII no más baja) en absoluto (pero tampoco devolverá porciones de ella).Desde la página de manual de pcrepattern;
En el modo UTF-8, los caracteres con valores superiores a 128 nunca coinciden con d, s o w, y siempre coinciden d, s y w.Esto es cierto incluso cuando el soporte de propiedad de personaje Unicode está disponible.
De Manejando UTF-8 con PHP.Por lo tanto, en realidad es irrelevante si su URL está codificada en ISO-8859-1 (mysite.local/citytest/M%FCnchen) o UTF-8 (mysite.local/citytest/M%C3%BCnchen), la expresión regular predeterminada no lo hará. fósforo.
También hice experimentos con diéresis en URL en Zend Framework y llegué a la conclusión de que realmente no querrías diéresis en tus URL.El problema es que no puedes confiar en la codificación utilizada por el navegador para la URL.Firefox (anterior a 3.0), por ejemplo, no codifica UTF-8 las URL ingresadas en el cuadro de texto de la dirección (si no se especifica en about:config) e IE tiene una casilla de verificación dentro de sus opciones para elegir entre codificación normal y UTF-8 para sus URL. .Pero si hace clic en enlaces dentro de una página, ambos navegadores usan la URL en la codificación dada (UTF-8 en una página UTF-8).Por lo tanto, no puede estar seguro de en qué codificación se envían las URL a su aplicación, y detectar la codificación utilizada no es tan trivial.
Quizás sea mejor utilizar parámetros transliterados en sus URL (p. ej.cambie Ä a Ae y así sucesivamente).Hay una forma realmente sencilla de hacer esto (no sé si funciona con todos los idiomas, pero lo estoy usando con cadenas en alemán y funciona bastante bien):
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, '-');
}
Otros consejos
Por favor me funciona perfecto
/^[\p{L}-. ]*$/u
^
Inicio de la cuerda[ ... ]*
Cero o más de los siguientes:\p{L}
Caracteres de letras Unicode–
guiones.
periodos- espacios
$
Fin de la cuerda/u
Habilitar el modo Unicode en PHP
EJEMPLO:
$str= ‘Füße’;
if (!preg_match(“/^[\p{L}-. ]*$/u”, $str))
{
echo ‘error’;
}
else
{
echo “success”;
}
El modificador u hace que la expresión regular espere una entrada utf-8.Esto sugeriría que ZF espera una entrada codificada en utf-8, y no en ISO-8859-1 (no estoy muy familiarizado con ZF, así que solo estoy adivinando).
Si ese es el caso, tendrás que codificación utf-8 el ü
antes de usarlo en una URL.Entonces pasaría a ser: mysite.local/citytest/M%C3%BCnchen
Tenga en cuenta que dado que el resto de su aplicación probablemente habla ISO-8859-1 (que es el valor predeterminado para PHP <= 5), tendrá que decodificar explícitamente la variable con utf8_decode, antes de poder usarlo.