Zend Framework 2: How to place a redirect into a module, before the application reaches a controller

Artyom Tokarev picture Artyom Tokarev · Jan 5, 2013 · Viewed 20.8k times · Source

Let's say we have a module named Cart and want to redirect users if some condition is met. I want to place a redirect at the module bootstrapping stage, before the application reaches any controller.

So here is the module code:

<?php
namespace Cart;

class Module
{
    function onBootstrap() {
        if (somethingIsTrue()) {
            // redirect
        }
    }
}
?>

I wanted to use the Url controller plugin, but it seems the controller instance is not available at this stage, at least I don't know how to get it.

Thanks in advance

Answer

yechabbi picture yechabbi · Jan 5, 2013

This should do the necessary work:

<?php
namespace Cart;

use Zend\Mvc\MvcEvent;

class Module
{
    function onBootstrap(MvcEvent $e) {
        if (somethingIsTrue()) {
            //  Assuming your login route has a name 'login', this will do the assembly
            // (you can also use directly $url=/path/to/login)
            $url = $e->getRouter()->assemble(array(), array('name' => 'login'));
            $response=$e->getResponse();
            $response->getHeaders()->addHeaderLine('Location', $url);
            $response->setStatusCode(302);
            $response->sendHeaders();
            // When an MvcEvent Listener returns a Response object,
            // It automatically short-circuit the Application running 
            // -> true only for Route Event propagation see Zend\Mvc\Application::run

            // To avoid additional processing
            // we can attach a listener for Event Route with a high priority
            $stopCallBack = function($event) use ($response){
                $event->stopPropagation();
                return $response;
            };
            //Attach the "break" as a listener with a high priority
            $e->getApplication()->getEventManager()->attach(MvcEvent::EVENT_ROUTE, $stopCallBack,-10000);
            return $response;
        }
    }
}
?>