2

今天我偶然发现了一个问题,这似乎是 Zend 框架中的一个错误。给定以下路线:

<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-修饰符用于处理亚洲字符。因为我不使用它们,所以我知道那个补丁很好。谢谢阅读。

4

3 回答 3

2
于 2011-06-23T10:06:00.017 回答
1

u 修饰符使正则表达式期望 utf-8 输入。这表明 ZF 需要 utf-8 编码输入,而不是 ISO-8859-1(我对 ZF 不太熟悉,所以我只是在这里猜测)。

如果是这种情况,您必须先对utf-8 进行编码ü然后才能在 URL 中使用它。然后它会变成:mysite.local/citytest/M%C3%BCnchen

请注意,由于您的应用程序的其余部分可能使用 ISO-8859-1(这是 PHP <= 5 的默认值),因此您必须使用utf8_decode显式解码变量,然后才能使用它。

于 2008-09-24T15:19:03.747 回答
1

问题如下:

使用 /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 编码之间进行选择. 但是,如果您单击页面内的链接,两个浏览器都会使用给定编码的 URL(UTF-8 页面上的 UTF-8)。因此,您无法确定将 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('/&szlig;/', '/&(..)lig;/', '/&([aouAOU])uml;/', '/&(.)[^;]*;/', '/\W/'),
        array('ss', '$1', '$1e', '$1', '-'),
        $name);
    $name=preg_replace('/-{2,}/', '-', $name);
    return trim($name, '-');
}
于 2008-09-27T18:25:27.770 回答