Attach a view strategy for specific modules

There have been some questions around in the IRC channel and on Twitter how you could enable the Json view strategy for only a specific module in Zend Framework 2. Because I was requiring this feature too in the near future, I started exploring the code behind Zend\View and its strategies, to make this happen.

In fact the code is really simple, but like others who struggled with it, it took a while before I got to the result. If you're not interested in the working, simply copy the example code below to your module class and it should work.

namespace MyModule;

use Zend\ModuleManager\Feature;
use Zend\EventManager\EventInterface;
use Zend\Mvc\MvcEvent;

class Module implements
    Feature\BootstrapListenerInterface
{
    public function onBootstrap(EventInterface $e)
    {
        $app = $e->getApplication();
        $em  = $app->getEventManager()->getSharedManager();
        $sm  = $app->getServiceManager();

        $em->attach(__NAMESPACE__, MvcEvent::EVENT_DISPATCH, function ($e) use ($sm) {
            $strategy = $sm->get('ViewJsonStrategy');
            $view     = $sm->get('ViewManager')->getView();
            $strategy->attach($view->getEventManager());
        });
    }
}

In this example, I start injecting the JsonStrategy only when controllers inside my module are dispatched. Therefore I listen to the "dispatch" event only for event managers having the identifier equal to my root namespace. Then I am sure every SomeController in MyModule will cause the event to fire, but any other OtherController from AnotherModule will not.

The strategy is retrieved from the service locator, where it's directly injected with a Json renderer too (so we don't need to care about that). The service manager has also a registered ViewManager, which is a Zend\Mvc\View\Http\ViewManager, connecting the MVC parts of the framework to the Zend\View component. This manager is obviously aware of a Zend\View\View responsible for rendering view scripts and so on. The view has its own event manager, triggering events to get a renderer and inject responses into the Response object. This is where the JsonStrategy wants to listen for, so the strategy attaches some listeners to the event manager of the view.

It took some time to figure this out, but hopefully others will benefit from this article and do not get stuck in exploring the MVC layers of Zend Framework 2.