关于Url编码的变音符号的路由问题(使用Zend框架)

时间:2008-09-24 14:12:06

标签: php zend-framework

今天我偶然发现了一个似乎是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不匹配,因此不会调用正确的控制器。有人知道为什么?

Fyi,哪里使用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-modifier用于处理亚洲字符。由于我没有使用它们,我知道这个补丁很好。谢谢你的阅读。

3 个答案:

答案 0 :(得分:2)

请它适合我的工作

/^[\p{L}-. ]*$/u
  • ^字符串的开头
  • [ ... ]*以下零个或多个:
  • \p{L} Unicode字母字符
  • 破折号
  • .
  • 空格
  • $字符串结尾
  • /u在PHP中启用Unicode模式

实施例

$str= ‘Füße’;
if (!preg_match(“/^[\p{L}-. ]*$/u”, $str))
{
    echo ‘error’;
}
else
{
    echo “success”;
}

答案 1 :(得分:1)

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

如果是这种情况,您必须utf-8 encode ü才能在网址中使用它。然后它将成为:mysite.local/citytest/M%C3%BCnchen

请注意,由于应用程序的其余部分可能会使用ISO-8859-1(默认情况下为PHP&lt; = 5),因此您必须先使用utf8_decode对变量进行显式解码,然后才能使用它

答案 2 :(得分:1)

问题如下:

  

使用/ u模式修饰符可以防止   被篡改的话,而是   PCRE跳过字符串   代码值大于127。   因此,\ w将不匹配   多字节(非低ascii)字   所有(但也不会返回部分)   它)。从pcrepattern手册页;

     

在UTF-8模式下,带有值的字符   大于128永远不会匹配\ d,\ s,   或\ W,并始终匹配\ D,\ S和   \ W。即使在Unicode时也是如此   角色属性支持是   可用。

来自Handling UTF-8 with PHP。 因此,如果您的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之前)没有UTF-8编码输入到地址文本框中的URL(如果未在about:config中指定),并且IE在其选项中有一个复选框,用于为其URL选择常规和UTF-8编码。但是,如果您单击页面中的链接,则两个浏览器都使用给定编码中的URL(UTF-8页面上的UTF-8)。因此,您无法确定将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, '-');
}