Php ZF2-使一个模块中的onbootstrap事件取代其他模块

Php ZF2-使一个模块中的onbootstrap事件取代其他模块,php,zend-framework2,Php,Zend Framework2,我有一个名为Browsercheck的ZF2模块,当与其他模块一起使用时,会检查用户的浏览器,如果浏览器不受支持,则会显示不受支持的浏览器页面。我遇到的问题是,当其他模块遇到异常或404错误时,Browsercheck的引导上的以下代码不是首选代码。不然就行了 如何确保此代码针对每个事件执行并取代任何其他事件?理想情况下,在ZF1中,我在index.php中使用这样的代码。。但不确定它在ZF2中应该是怎样的。基本上,如果浏览器不受支持,那么无论它是404还是异常都不重要。它应该继续并呈现不受支持

我有一个名为Browsercheck的ZF2模块,当与其他模块一起使用时,会检查用户的浏览器,如果浏览器不受支持,则会显示不受支持的浏览器页面。我遇到的问题是,当其他模块遇到异常或404错误时,Browsercheck的引导上的以下代码不是首选代码。不然就行了

如何确保此代码针对每个事件执行并取代任何其他事件?理想情况下,在ZF1中,我在index.php中使用这样的代码。。但不确定它在ZF2中应该是怎样的。基本上,如果浏览器不受支持,那么无论它是404还是异常都不重要。它应该继续并呈现不受支持的浏览器页面

public function onBootstrap(MvcEvent $e)
{   
    $sharedEvents = $e->getApplication()->getEventManager()->getSharedManager();
    $sharedEvents->attach('Zend\Mvc\Controller\AbstractController','dispatch',
    function($event)
    {
        $browser = new \BrowserCheck\Service\BrowserCheck();
        if (!$browser->isCompatible())
        {
            $viewModel = new \Zend\View\Model\ViewModel();
            $viewModel->setTerminal(true);

            $request = $event->getRequest();
            $response = $event->getResponse();


            $viewModel->setTemplate('browser-check/index/index.phtml');
            //Replace the entire view
            $event->setViewModel($viewModel);
            $event->stopPropagation();
            $response->setStatusCode(200);
            return $viewModel;
        }
    });
}
更新:


这里的问题是在调度事件上注册事件侦听器,该事件发生在引导和路由事件之后。如果在route event(路由事件)时触发的事件侦听器无法识别路由,则会收到404错误页面,并且在调用任何其他调度事件侦听器之前,应用程序生命周期将终止

为了在应用任何路由之前调用事件侦听器,您现在有两个选项:

在引导事件上以较低优先级(例如低于10000)注册事件侦听器 或者以更高的优先级在路由侦听器上注册它,10应该足够了 根据,调用onBoostrap模块方法的优先级为10000,调用\Zend\Mvc\ModuleRouteListener和\Zend\Mvc\RouteListener的onRoute方法的优先级为1,优先级越高

编辑:

你应该这样做:

public function onBootstrap(MvcEvent $e)
{
    /* ... all the default stuff here ... */


    $this->registerBrowserCheckEvent($e);
}

private function registerBrowserCheckEvent(MvcEvent $e)
{
    $eventManager = $e->getApplication()->getEventManager();
    $browserEventListener = function ($event) {
        $browser = new \BrowserCheck\Service\BrowserCheck();
        if (!$browser->isCompatible()) {
            $viewModel = new \Zend\View\Model\ViewModel();
            $viewModel->setTerminal(true);

            $request = $event->getRequest();
            $response = $event->getResponse();

            $viewModel->setTemplate('browser-check/index/index.phtml');

            //Replace the entire view
            $event->setViewModel($viewModel);
            $event->stopPropagation();
            $response->setStatusCode(200);
            return $viewModel;
        }
    };

    $eventManager->attach(MvcEvent::EVENT_BOOTSTRAP, $browserEventListener, 100);
}

另外,请注意,ZF2至少使用PSR-2,您的代码应遵循此约定,同时请注意您的代码与我的代码之间的细微差异。

此模块浏览器检查在您的应用程序配置中定义在哪个位置?你试过把它放在第一位吗?我确实放在了第一位。。还是一样的问题。好吧,那试试最后一个位置怎么样?对不起。我也这么做了。同样的问题。除了404和异常之外,该代码一直有效。不知何故,他们更喜欢这个,我不明白为什么。我也不明白,因为你把代码放进了你的onBoostrap方法中,应该在路由之前处理它。bootstrap事件作为所有事件中的第一个事件被触发,所有注册模块的bootstrap方法应该首先被调用,尽管我不清楚它们被调用的顺序。之后,触发路由事件,这就是404发生的地方。对PHP异常一无所知。您是否想过将这个特殊的浏览器处理移到index.php中?只是作为一个边缘案例解决方案来尝试?请参阅我的更新上面。当控制器操作发生异常和404时,上面更新的代码正在工作。但是,如果发生控制器未找到错误,则不会执行该命令。你能建议我如何修复它吗?@Jake你的目标是AbstractController事件管理器;如果找不到控制器,则AbstractController::dispatch将永远不会被触发。您应该将侦听器附加到应用程序服务管理器,而不是SharedEventManager。@alexp您能提供一个示例吗?
public function onBootstrap(MvcEvent $e)
{
    /* ... all the default stuff here ... */


    $this->registerBrowserCheckEvent($e);
}

private function registerBrowserCheckEvent(MvcEvent $e)
{
    $eventManager = $e->getApplication()->getEventManager();
    $browserEventListener = function ($event) {
        $browser = new \BrowserCheck\Service\BrowserCheck();
        if (!$browser->isCompatible()) {
            $viewModel = new \Zend\View\Model\ViewModel();
            $viewModel->setTerminal(true);

            $request = $event->getRequest();
            $response = $event->getResponse();

            $viewModel->setTemplate('browser-check/index/index.phtml');

            //Replace the entire view
            $event->setViewModel($viewModel);
            $event->stopPropagation();
            $response->setStatusCode(200);
            return $viewModel;
        }
    };

    $eventManager->attach(MvcEvent::EVENT_BOOTSTRAP, $browserEventListener, 100);
}