Маршрут с особыми символами не корректно обрабатывается в Zend Framework 2

URI с немецкими специальными символами не работают (ошибка 404). У меня уже была эта проблема ( здесь ), и она была разрешена с помощью модификатора unicode и специального помощника вида , который его использует.

Теперь у меня такая же проблема с дочерним маршрутом Segment , но на этот раз подход с идентификатором unicode и специальным помощником просмотра не работает.

Все запросы, такие как sld.tld/sport/sportäöüÄÖÜß/cityäöüÄÖÜß или sld.tld/sport/sportäöüÄÖÜß/cityäöüÄÖÜß/page/123 , заканчиваются ошибкой 404 .

/module/Catalog/config/module.config.php

 <?php return array( ... 'router' => array( 'routes' => array( 'catalog' => array( ... ), 'city' => array( ... ), // works correctly, if I remove the child route 'sport' => array( 'type' => 'MyNamespace\Mvc\Router\Http\UnicodeRegex', 'options' => array( 'regex' => '/catalog/(?<city>[\p{L}\p{Zs}]*)/(?<sport>[\p{L}\p{Zs}]*)', 'defaults' => array( 'controller' => 'Catalog\Controller\Catalog', 'action' => 'list-courses', ), 'spec' => '/catalog/%city%/%sport%', ), 'may_terminate' => true, 'child_routes' => array( 'courses' => array( 'type' => 'segment', 'options' => array( 'route' => '[/page/:page]', 'defaults' => array( 'controller' => 'Catalog\Controller\Catalog', 'action' => 'list-courses', ), ), 'may_terminate' => true, ), ) ), ), ), ... ); 

Я также пробовал его с дочерним маршрутом UnicodeRegex :

  'sport' => array( 'type' => 'MyNamespace\Mvc\Router\Http\UnicodeRegex', 'options' => array( 'regex' => '/catalog/(?<city>[\p{L}\p{Zs}]*)/(?<sport>[\p{L}\p{Zs}]*)', 'defaults' => array( 'controller' => 'Catalog\Controller\Catalog', 'action' => 'list-courses', ), 'spec' => '/catalog/%city%/%sport%', ), 'may_terminate' => true, 'child_routes' => array( 'courses' => array( 'type' => 'MyNamespace\Mvc\Router\Http\UnicodeRegex', 'options' => array( 'regex' => '/page/(?<page>[\p{N}]*)', 'defaults' => array( 'controller' => 'Catalog\Controller\Catalog', 'action' => 'list-courses', ), 'spec' => '/page/%page%', ), 'may_terminate' => true, ), ) ), 

UnicodeRegex

см. здесь

UnicodeSegment

Расширяет Zend\Mvc\Router\Http\Segment и завершает ввод вызовов ALL preg_match(...) с помощью u :

  • '((\G(?P<literal>[^:{\[\]]*)(?P<token>[:{\[\]]|$)))u'
  • '(\G\{(?P<name>[^}]+)\}:?)u'
  • '((\G(?P<name>[^:/{\[\]]+)(?:{(?P<delimiters>[^}]+)})?:?))u'
  • '(\G(?P<literal>[^}]+)\})u'
  • '(\G' . $this->regex . ')u'
  • '(^' . $this->regex . '$)u'

Как заставить его работать?

Solutions Collecting From Web of "Маршрут с особыми символами не корректно обрабатывается в Zend Framework 2"

Просто взгляните на это, вам нужно изменить UnicodeRegex соответствия UnicodeRegex чтобы он вернул правильную длину для той части URL, которую он сопоставил, вот попытка исправить то, что, кажется, работает (по крайней мере для меня) с вашей установки

 public function match(Request $request, $pathOffset = null) { if (!method_exists($request, 'getUri')) { return null; } $uri = $request->getUri(); $path = rawurldecode($uri->getPath()); 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; } foreach ($matches as $key => $value) { if (is_numeric($key) || is_int($key) || $value === '') { unset($matches[$key]); } else { $matches[$key] = rawurldecode($value); } } // at this point there's a mismatch between the length of the rawurlencoded path // that all other route helpers use, so we need to match their expectations // to do that we build the matched part from the spec, using the matched params $url = $this->spec; $mergedParams = array_merge($this->defaults, $matches); foreach ($mergedParams as $key => $value) { $spec = '%' . $key . '%'; if (strpos($url, $spec) !== false) { $url = str_replace($spec, rawurlencode($value), $url); } } // make sure the url we built from spec exists in the original uri path if (false === strpos($uri->getPath(), $url)) { return null; } // now we can get the matchedLength $matchedLength = strlen($url); return new RouteMatch($mergedParams, $matchedLength); } не public function match(Request $request, $pathOffset = null) { if (!method_exists($request, 'getUri')) { return null; } $uri = $request->getUri(); $path = rawurldecode($uri->getPath()); 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; } foreach ($matches as $key => $value) { if (is_numeric($key) || is_int($key) || $value === '') { unset($matches[$key]); } else { $matches[$key] = rawurldecode($value); } } // at this point there's a mismatch between the length of the rawurlencoded path // that all other route helpers use, so we need to match their expectations // to do that we build the matched part from the spec, using the matched params $url = $this->spec; $mergedParams = array_merge($this->defaults, $matches); foreach ($mergedParams as $key => $value) { $spec = '%' . $key . '%'; if (strpos($url, $spec) !== false) { $url = str_replace($spec, rawurlencode($value), $url); } } // make sure the url we built from spec exists in the original uri path if (false === strpos($uri->getPath(), $url)) { return null; } // now we can get the matchedLength $matchedLength = strlen($url); return new RouteMatch($mergedParams, $matchedLength); }