【问题标题】:URIs with german special characters don't work (error 404) in Zend Framework 2带有德语特殊字符的 URI 在 Zend Framework 2 中不起作用(错误 404)
【发布时间】:2013-03-16 02:54:24
【问题描述】:

我想获取一个城市列表,其中每个城市名称都被链接并引用该城市的页面:

链接(在视图脚本中创建)如下所示:

http://project.loc/catalog/Berlin (in the HTML source code url-encoded: Berlin)
http://project.loc/catalog/Erlangen (in the HTML source code url-encoded: Erlangen)
http://project.loc/catalog/Nürnberg (in the HTML source code url-encoded: N%C3%BCrnberg)

“Berlin”、“Erlangen”等有效,但如果城市名称包含德语特殊字符(äöüÄÖÜß) 像“纽伦堡”一样,出现 404 错误:

发生 404 错误页面未找到。请求的 URL 不能是 通过路由匹配。没有可用的例外

为什么?以及如何让它发挥作用?

提前致谢!

编辑:

我的路由器设置:

'router' => array(
    'routes' => array(
        'catalog' => array(
            'type'  => 'literal',
            'options' => array(
                'route' => '/catalog',
                'defaults' => array(
                    'controller' => 'Catalog\Controller\Catalog',
                    'action'     => 'list-cities',
                ),
            ),
            'may_terminate' => true,
            'child_routes' => array(
                'city' => array(
                    'type'  => 'segment',
                    'options' => array(
                        'route' => '/:city',
                        'constraints' => array(
                            'city'  => '[a-zA-ZäöüÄÖÜß0-9_-]*',
                        ),
                        'defaults' => array(
                            'controller' => 'Catalog\Controller\Catalog',
                            'action'     => 'list-sports',
                        ),
                    ),
                    'may_terminate' => true,
                    'child_routes' => array(
                    // ...
                    ),
                ),
            ),
        ),
    ),
),

【问题讨论】:

  • 这与你定义的constraints不匹配不是很明显吗?
  • 是的,你是对的。我刚刚编辑了路由器设置。它仍然无法正常工作。
  • 您展示了 URL 的“外观”——但是您是否为这些特殊字符使用了正确的 URL 编码?
  • 不,我没有。我将城市名称设置为 URI,以便它们如何来自数据库($city->name 而不是 urlencode($city->name))。
  • 如果您自己不对 URL 中的特殊字符进行 urlencode,则将其留给客户端 - 这样您很容易遇到使用的字符编码问题。

标签: uri url-routing zend-framework2 zend-framework-routing url-helper


【解决方案1】:

您需要更改约束,可以使用匹配 UTF8 字符的正则表达式,如下所示:

'/[\p{L}]+/u'

注意 /u 修饰符(unicode)。

编辑:

问题是resolved

解释:

RegEx 路由将 URI 与 preg_match(...) 匹配(Zend\Mvc\Router\Http\Regex 的 116118 行)。为了使用“特殊字符”(128+)来处理字符串,必须将模式修饰符u 传递给preg_match(...)。像这样:

$thisRegex = '/catalog/(?<city>[\p{L}]*)';
$regexStr = '(^' . $thisRegex . '$)u'; // <-- here
$path = '/catalog/Nürnberg';
$matches = array();
preg_match($regexStr, $path, $matches);

而且由于 RegEx Route 将一个 url 编码的字符串传递给 preg_match(...),因此需要先对字符串进行解码:

$thisRegex = '/catalog/(?<city>[\p{L}]*)';
$regexStr = '(^' . $thisRegex . '$)u';
$path = rawurldecode('/catalog/N%C3%BCrnberg');
$matches = array();
preg_match($regexStr, $path, $matches);

RegEx Route 中没有提供这两个步骤,因此 preg_match(...) 会得到一个类似 '/catalog/N%C3%BCrnberg' 的 steing 并尝试将其加工成一个像 '/catalog/(?&lt;city&gt;[\\p{L}]*)/u' 这样的正则表达式

解决方案是使用自定义 RegEx 路由。 Here 就是一个例子。

【讨论】:

  • 谢谢!这对我不起作用,但也许我错误地使用了你的正则表达式。我已将 'city' =&gt; '[a-zA-ZäöüÄÖÜß0-9_-]*', 替换为 'city' =&gt; '/^\p{L}[\p{L} _.-]+$/u',
  • 也许这是一个糟糕的例子,它只是为了说明 /u 标志。试试 '/[\p{L}]+/u'
  • 终于成功了!感谢您对修饰符的重要提示!
  • 我已经发布了解释和解决方案的链接,作为您答案的补充。什么意思?
  • 我将此添加到我的修饰符中:/[\p{L}]+/u 但仍然无法正常工作。 Automatix,可以分享一下你用过的吗?
猜你喜欢
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
  • 2013-12-30
  • 2013-06-03
  • 1970-01-01
  • 2014-03-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多