如何在Zend框架2中为RegEx路由设置(UTF8)修饰符


How to set a (UTF8) modifier for RegEx of a RegEx Route in Zend Framework 2?

我在uri中遇到(德语)特殊字符的麻烦,并想尝试用RegEx路由和用于UTF-8 u的PCRE模式修饰符来解决它。

'router' => array(
    'routes' => array(
        // ...
        'city' => array(
            'type'  => 'regex',
            'options' => array(
                'regex' => '/catalog/(?<city>[a-zA-Z0-9_-äöüÄÖÜß]*)'/u',
                'defaults' => array(
                    'controller' => 'Catalog'Controller'Catalog',
                    'action'     => 'list-sports',
                ),
                'spec'  => '/catalog/%city%',
            ),
            'may_terminate' => true,
        ),
    ),
),

但是当我设置它时,路由完全停止工作(错误404)—无论是对于带有特殊字符的uri还是对于没有特殊字符的uri。

如何正确设置修饰语?

因为我已经打开了这个,所以这里有一个处理程序来解决这个问题。

<?php
namespace Application'Mvc'Router'Http;
use Zend'Mvc'Router'Http'Regex;
use Zend'Mvc'Router'Http'RouteMatch;
use Zend'Stdlib'RequestInterface as Request;
class UnicodeRegex extends Regex
{
    /**
     * match(): defined by RouteInterface interface.
     *
     * @param  Request $request
     * @param  integer $pathOffset
     * @return RouteMatch
     */
    public function match(Request $request, $pathOffset = null)
    {
        if (!method_exists($request, 'getUri')) {
            return null;
        }
        $uri  = $request->getUri();
        // path decoded before match
        $path = rawurldecode($uri->getPath());
        // regex with u modifier    
        if ($pathOffset !== null) {
            $result = preg_match('('G' . $this->regex . ')u', $path, $matches, null, $pathOffset);
        } else {
            $result = preg_match('(^' . $this->regex . '$)u', $path, $matches);
        }
        if (!$result) {
            return null;
        }
        $matchedLength = strlen($matches[0]);
        foreach ($matches as $key => $value) {
            if (is_numeric($key) || is_int($key) || $value === '') {
                unset($matches[$key]);
            } else {
                $matches[$key] = $value;
            }
        }
        return new RouteMatch(array_merge($this->defaults, $matches), $matchedLength);
    }
}

假设你把文件放在Application/Mvc/Router/Http/UnicodeRegex中,你的路由定义应该是这样的

'router' => array(
    'routes' => array(
        // ...
        'city' => array(
            'type'  => 'Application'Mvc'Router'Http'UnicodeRegex',
            'options' => array(
                'regex' => '/catalog/(?<city>['p{L}]+)',
                // or if you prefer, your original regex should work too
                // 'regex' => '/catalog/(?<city>[a-zA-Z0-9_-äöüÄÖÜß]*)',
                'defaults' => array(
                    'controller' => 'Catalog'Controller'Catalog',
                    'action'     => 'list-sports',
                ),
                'spec'  => '/catalog/%city%',
            ),
            'may_terminate' => true,
        ),
    ),
),

嗯,

我想你可以像其他许多人遇到同样的问题一样轻松地解决它。来看看其中的一些:

*正则表达式中的UTF-8

使用以下修饰符,如''s, ''p{L}''u来帮助您。我希望它能解决!好运。

编辑

见my own test:

<?php
    $toss_the_dice = utf8_decode ("etc/catalog/Nürnberg");
    preg_match ('/'/catalog'/([''s''p{L}]*)/m', $toss_the_dice, $dice);
    echo utf8_encode ($dice[1]);
// Now it prints
// Nürnberg
?>

你能意识到吗?

编辑2

这对你来说会更好!

<?php
    $toss_the_dice = "etc/catalog/Nürnberg";
    preg_match ('/'/catalog'/([''s''p{L}]*)/u', $toss_the_dice, $dice);
    echo $dice[1];
// Now it also prints
// Nürnberg
?>