Reputation: 26117
I have a ZF2 module called "Browsercheck", when used with other modules, checks the user's browser and shows an "Unsupported Browser" page if the browser is not supported. The issue I am having is, that the following code which is onBootstrap of the "Browsercheck" is not taking the first preference when other modules encounter an exception or a 404 error. IT works otherwise.
How can I make sure this code executes for every event and supersede any other event? Ideally in ZF1, I use code like this in index.php.. but not sure how it should be in ZF2. Basically if the browser is not supported, it shouldn't matter whether it's a 404 or an exception. It should go ahead and render the unsupported browser page.
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;
}
});
}
UPDATE:
$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);
Upvotes: 0
Views: 1131
Reputation: 16055
The problem here is that you register your event listener on the dispatch
event, which occurs after bootstrap
and after route
events. If the event listener triggered at route
event cannot identify the route, you receive a 404
error page and the application lifecycle is terminated before any other dispatch
event listener could be invoked.
In order to invoke your event listener before any routing is applied, you now have two options:
bootstrap
event with lower prio (e.g. lower than 10000
)route
listener with some higher priority, 10
should be enoughAccording to ZF2 doc page, onBoostrap()
module methods are called with priority 10000
and onRoute()
methods of \Zend\Mvc\ModuleRouteListener
and \Zend\Mvc\RouteListener
are called with priority 1
(higher the number higher the priority).
EDIT:
You should be doing something like this:
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);
}
Also please notice that ZF2 uses PSR-2 (at least) and your code should follow this convention as well (mind the small differences between your code and mine).
Upvotes: 0