Как установить модификатор (UTF8) для RegEx маршрута RegEx в Zend Framework 2?

У меня проблемы с (немецкими) специальными символами в URI, и я хочу попытаться разрешить их с помощью маршрута RegEx и модификатора шаблона PCRE для UTF-8. u,

'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, ни для тех, у которых нет специальных символов.

Как правильно установить модификатор?

2 ответа

Решение

Поскольку у меня уже было это открыто, вот обработчик, который решает проблему.

<?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 чтобы помочь вам. Я надеюсь, что это решает! Удачи.

редактировать

Смотрите мой собственный тест:

<?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

?>
Другие вопросы по тегам