繁体   English   中英

ZF2主机名匹配汇编URL和404

[英]ZF2 hostname match assemble url and 404

我有以下代码将路由与主机名匹配;

'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); ?> <?= $this->url('website/languages', [], true); ?> ,但那一团糟。 因为我只想使用当前路由的TLD和语言环境。

因此,我提供了扩展URL视图帮助程序的解决方案。 并在未使用路由匹配设置时设置localetld参数。 这适用于1个“次要”问题,请参见2。但想知道是否有更好的解决方案。

2. 404 paga

在1中,我使用当前的路由匹配来获取locale / tld来组装url,这一切都适用,除了404页面。 因为没有路由匹配,所以很明显。

我开始挖掘周围环境,并从service locator找到路由器。 我试图获取仅返回Zend\\Mvc\\Router\\Http\\Part website的路由。 protected $routeZend\\Mvc\\Router\\Http\\Hostname ,无法访问。 那样就没有运气了。

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

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

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

好吧,我继续寻找和思考,并提出了“解决方案”。

解决2.解决了我创建了一个监听MvcEvent::EVENT_DISPATCH_ERROR监听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. 然后在事件中注入routematch

解决方法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
    );
}

这不是最优雅的方法,但目前可以使用

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM