我有以下代码来匹配具有主机名的路由;
'router' => [
'router_class' => 'Zend\Mvc\Router\Http\TranslatorAwareTreeRouteStack',
'routes' => [
'website' => [
'type' => 'hostname',
'may_terminate' => true,
'options' => [
'route' => ':locale.domain.:tld',
'constraints' => [
'language' => '(nl|en)',
'tld' => '(dev|org)',
],
],
]
],
],
和一些匹配uri的路线。
因此,在开发中我可以拥有en.domain.dev
和nl.domain.dev
等路线。路线的翻译也像魅力一样,然后我的“问题”发生了
1。汇编网址
对于每个网址,我现在需要locale
和tld
变量。要做到这一点,我做<?= $this->url('website/languages', [], true); ?>
,但这使它变得一团糟。因为我只想使用当前路线的TLD和区域设置。
所以我提供了扩展URL视图助手的解决方案。并且在未使用路由匹配设置时设置locale
和tld
参数。这适用于1'次要'问题,见2.但是想知道是否有一个更好的解决方案。
2。 404 paga
在1中,我使用当前路线匹配来获取locale
/ tld
来组装网址,这一切都有效,除了404页面。因为显然没有路线匹配。
当我找到路由器(来自service locator
)时,我开始挖掘arround。我试图获取website
的路由它只返回Zend\Mvc\Router\Http\Part
。
protected $route
是无法访问的Zend\Mvc\Router\Http\Hostname
。所以没那么幸运。
我获得主机名路由的唯一方法是将其构建为我自己,我不想这样做。
所以问题是如何轻松地重用主机名参数,并在404页面上获取主机名参数?
我知道例如test.domain.test与主机名不匹配,并且会提供损坏的主机名,但这是Nginx的问题。因此,Nginx将确保主机名始终正确
答案 0 :(得分:1)
我继续搜索和思考,并提出了一个解决方案&#39;
解决 2。我创建了一个侦听MvcEvent::EVENT_DISPATCH_ERROR
的侦听器。
代码;
// use are above the class declaration
use Zend\Mvc\Router\Http\TranslatorAwareTreeRouteStack;
use Zend\EventManager\AbstractListenerAggregate;
use Zend\EventManager\EventManagerInterface;
use Zend\Http\PhpEnvironment\Request;
use Zend\Mvc\Router\Http\RouteMatch;
use Zend\Mvc\MvcEvent;
public function onDispatchError(MvcEvent $event)
{
if (is_null($event->getRouteMatch())) {
$router = $event->getRouter();
$request = $event->getRequest();
if ($router instanceof TranslatorAwareTreeRouteStack && $request instanceof Request) {
$match = $router->getRoute('website')->match($request, strlen($request->getUri()->getPath()), array(
'translator' => $router->getTranslator(),
));
if ($match instanceof RouteMatch) {
$match->setMatchedRouteName('website');
$event->setRouteMatch($match);
}
}
}
}
它的作用;
检查是否有路线匹配,如果不是404
检查$router
是TranslatorAwareTreeRouteStack
,$request
是HttpRequest
获取website
的路线(这是主机名的路线
然后它匹配它(诀窍是设置了偏移量,所以只检查了主机名)
设置路由匹配名称(如果未设置则为空,这将导致问题)
然后在事件中注入路线匹配
要解决 1。我现在总是可以访问route match
所以我可以做一些自己的魔法。我扩展了url viewhelper
。
public function __invoke(
$name = null,
$params = array(),
$options = array(),
$reuseMatchedParams = false
) {
if ($this->routeMatch instanceof RouteMatch) {
foreach(['locale', 'tld'] as $key) {
if (!array_key_exists($key, $params)) {
$params[$key] = $this->routeMatch->getParam($key);
}
}
}
// This is needed for the magic that can happen when `reuseMatchedParams` is used at the third position
if (is_bool($options)) {
$reuseMatchedParams = $options;
$options = array();
}
return parent::__invoke(
$name,
$params,
$options,
$reuseMatchedParams
);
}
不是最优雅的方法,但现在可以使用