2

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

在此处输入图像描述

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

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”等有效,但如果城市名称包含德语特殊字符(äöüÄÖÜß),如“Nürnberg”,则会出现 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(
                    // ...
                    ),
                ),
            ),
        ),
    ),
),
4

1 回答 1

2

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

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

注意 /u 修饰符(unicode)。

编辑:

问题解决了。

解释:

RegEx Route 将 URI 与preg_match(...)(Zend\Mvc\Router\Http\Regex 的第116118行)匹配。为了使用“特殊字符”(128+)来处理字符串,必须将模式修饰符传递upreg_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(...)得到一个类似的 steing'/catalog/N%C3%BCrnberg'并尝试将其加工成一个类似的正则表达式'/catalog/(?<city>[\\p{L}]*)/u'

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

于 2013-03-26T11:33:57.670 回答