ZF2主机名匹配汇编网址和404

时间:2014-09-26 14:18:46

标签: php zend-framework zend-framework2 zend-framework-mvc

我有以下代码来匹配具有主机名的路由;

'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.devnl.domain.dev等路线。路线的翻译也像魅力一样,然后我的“问题”发生了

1。汇编网址

对于每个网址,我现在需要localetld变量。要做到这一点,我做<?= $this->url('website/languages', [], true); ?>,但这使它变得一团糟。因为我只想使用当前路线的TLD和区域设置。

所以我提供了扩展URL视图助手的解决方案。并且在未使用路由匹配设置时设置localetld参数。这适用于1'次要'问题,见2.但是想知道是否有一个更好的解决方案。

2。 404 paga

在1中,我使用当前路线匹配来获取locale / tld来组装网址,这一切都有效,除了404页面。因为显然没有路线匹配。

当我找到路由器(来自service locator)时,我开始挖掘arround。我试图获取website的路由它只返回Zend\Mvc\Router\Http\Partprotected $route是无法访问的Zend\Mvc\Router\Http\Hostname。所以没那么幸运。

我获得主机名路由的唯一方法是将其构建为我自己,我不想这样做。

所以问题是如何轻松地重用主机名参数,并在404页面上获取主机名参数?

我知道例如test.domain.test与主机名不匹配,并且会提供损坏的主机名,但这是Nginx的问题。因此,Nginx将确保主机名始终正确

1 个答案:

答案 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);
            }
        }

    }
}

它的作用;

  1. 检查是否有路线匹配,如果不是404

  2. 检查$routerTranslatorAwareTreeRouteStack$requestHttpRequest

  3. 获取website的路线(这是主机名的路线

  4. 然后它匹配它(诀窍是设置了偏移量,所以只检查了主机名)

  5. 设置路由匹配名称(如果未设置则为空,这将导致问题)

  6. 然后在事件中注入路线匹配

  7. 要解决 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
        );
    }
    

    不是最优雅的方法,但现在可以使用