ZF2-使一个模块中的启动事件取代其他模块


ZF2 - Make onbootstrap events in one module supersede every other module

我有一个名为"Browsercheck"的ZF2模块,当与其他模块一起使用时,它会检查用户的浏览器,如果浏览器不受支持,则会显示"不支持的浏览器"页面。我遇到的问题是,当其他模块遇到异常或404错误时,"Browsercheck"的Bootstrap上的以下代码没有优先考虑。IT则不然。

如何确保此代码对每个事件都执行,并取代任何其他事件?理想情况下,在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;
        }
    });
}

更新:

$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;
        }
    };
$sharedEvents = $e->getApplication()->getEventManager()->getSharedManager();
$sharedEvents->attach('Zend'Mvc'Controller'AbstractController',
  array('dispatch','dispatch.error'), $browserEventListener, 100);

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

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

  • 在具有较低prio(例如,低于10000)的bootstrap事件上注册您的事件侦听器
  • 或者要在具有更高优先级的route侦听器上注册它,10就足够了

根据ZF2文档页面,onBoostrap()模块方法调用优先级为10000'Zend'Mvc'ModuleRouteListener'Zend'Mvc'RouteListeneronRoute()方法调用优先级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(至少),您的代码也应该遵循此约定(注意您的代码和我的代码之间的微小差异)。