有关 Url 编码变音符号的路由问题(使用 Zend 框架)
-
02-07-2019 - |
题
今天我偶然发现了一个问题,它似乎是 Zend-Framework 中的一个错误。给定以下路线:
<test>
<route>citytest/:city</route>
<defaults>
<controller>result</controller>
<action>test</action>
</defaults>
<reqs>
<city>.+</city>
</reqs>
</test>
和三个网址:
- mysite.local/citytest/柏林
- mysite.local/citytest/汉堡
- mysite.local/citytest/M%FCnchen
最后一个 URL 不匹配,因此不会调用正确的控制器。有人知道为什么吗?
仅供参考,在哪里使用 Zend-Framework 1.0(是的,我知道那很古老,但我不负责更改它:-/)
编辑:据我所知,我们很快就会升级到 Zend 1.5.6,但我不知道什么时候,所以如果有一个补丁就好了。
编辑:我已经追踪到以下行(Zend/Controller/Router/Route.php:170):
$regex = $this->_regexDelimiter . '^' .
$part['regex'] . '$' .
$this->_regexDelimiter . 'iu';
如果我把它改成
$this->_regexDelimiter . 'i';
有用。据我了解, u 修饰符用于处理亚洲字符。因为我不使用它们,所以我对那个补丁很满意。谢谢阅读。
解决方案
问题如下:
使用 /U模式修饰符可以防止单词被弄脏,而是PCRE跳过了代码值大于127的字符字符串。因此, w根本不匹配多键(非慢速ASCII)单词(但也不会返回其部分)。来自 pcrepattern 手册页;
在UTF-8模式下,值大于128的字符永远不匹配 d, s或 w,并且始终匹配 d, s和 w。即使有Unicode字符属性支持,也是如此。
从 使用 PHP 处理 UTF-8。因此,如果您的 URL 是 ISO-8859-1 编码 (mysite.local/citytest/M%FCnchen) 或 UTF-8 编码 (mysite.local/citytest/M%C3%BCnchen),则实际上无关紧要,默认正则表达式不会匹配。
我还在 Zend Framework 中的 URL 中对变音符号进行了实验,并得出结论:您实际上并不希望在 URL 中使用变音符号。问题是,您不能依赖浏览器对 URL 使用的编码。例如,Firefox(3.0 之前的版本)不会对地址文本框中输入的 URL 进行 UTF-8 编码(如果未在 about:config 中指定),而 IE 的选项中确实有一个复选框,可以在其 URL 的常规编码和 UTF-8 编码之间进行选择。但是,如果您单击页面内的链接,则两个浏览器都会使用给定编码(UTF-8 页面上的 UTF-8)的 URL。因此,您无法确定 URL 使用哪种编码发送到您的应用程序 - 并且检测所使用的编码并不是一件容易的事。
也许在 URL 中使用音译参数会更好(例如将 ä 更改为 Ae 等)。有一个非常简单的方法(我不知道这是否适用于每种语言,但我将它与德语字符串一起使用,并且效果很好):
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, '-');
}
其他提示
请它对我来说非常完美
/^[\p{L}-. ]*$/u
^
字符串的开头[ ... ]*
以下零个或多个:\p{L}
Unicode 字母字符–
破折号.
时期- 空间
$
字符串结尾/u
在 PHP 中启用 Unicode 模式
例子:
$str= ‘Füße’;
if (!preg_match(“/^[\p{L}-. ]*$/u”, $str))
{
echo ‘error’;
}
else
{
echo “success”;
}