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'
Как заставить его работать?
Просто взгляните на это, вам нужно изменить 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); }