ZF2 - Сделать события onbootstrap в одном модуле заменять любой другой модуль

У меня есть модуль ZF2 "Browsercheck", который при использовании с другими модулями проверяет браузер пользователя и показывает страницу "Unsupported Browser", если браузер не поддерживается. Проблема, с которой я столкнулся, заключается в том, что следующий код onBootstrap "Browsercheck" не принимает первое предпочтение, когда другие модули сталкиваются с исключением или ошибкой 404. ЭТО работает иначе.

Как я могу убедиться, что этот код выполняется для каждого события и заменяет любое другое событие? В идеале в 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);

1 ответ

Проблема в том, что вы регистрируете слушателя событий на dispatch событие, которое происходит после bootstrap и после route События. Если слушатель события сработал в route событие не может определить маршрут, вы получаете 404 страница ошибки и жизненный цикл приложения завершается раньше, чем любой другой dispatch прослушиватель событий может быть вызван.

Чтобы вызвать прослушиватель событий до применения какой-либо маршрутизации, теперь у вас есть два варианта:

  • либо зарегистрируйте прослушиватель событий на bootstrap событие с более низким приоритетом (например, ниже, чем 10000)
  • или зарегистрировать его на route слушатель с более высоким приоритетом, 10 должно быть достаточно

Согласно странице документа ZF2, onBoostrap() методы модуля вызываются с приоритетом 10000 а также onRoute() методы \Zend\Mvc\ModuleRouteListener а также \Zend\Mvc\RouteListener вызываются с приоритетом 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 (по крайней мере), и ваш код должен также следовать этому соглашению (учтите небольшие различия между вашим кодом и моим).

Другие вопросы по тегам