带有德语特殊字符的URI不起作用(错误404)。我已经遇到了这个问题(here),并且已经使用unicode modifier和custom view helper解决了这个问题。
现在我对Segment
子路由有同样的问题,但这次使用unicode标识符和自定义视图助手的方法不起作用。
sld.tld/sport/sportäöüÄÖÜß/cityäöüÄÖÜß
或sld.tld/sport/sportäöüÄÖÜß/cityäöüÄÖÜß/page/123
等Alle请求以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
请参阅here
UnicodeSegment
扩展Zend\Mvc\Router\Http\Segment
并使用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'
如何让它运作?
答案 0 :(得分:3)
刚看了一眼,你需要更改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);
}