I created an event listener and attached it to a specific controller
in onBootstrap
. The problem is that __invoke
function is called after controller action called. Everything except this is working fine.
Factories
public function getServiceConfig() {
return array(
'factories' => array(
'Api\Adapter\HeaderAuthentication' => 'Api\Factory\AuthenticationAdapterFactory',
'Api\Listener\AuthenticationListener' => 'Api\Factory\AuthenticationListenerFactory',
),
);
}
Bootstrap
public function onBootstrap(MvcEvent $e) {
$app = $e->getApplication();
$sm = $app->getServiceManager();
$em = $app->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($em);
$listener = $sm->get('Api\Listener\AuthenticationListener');
$em->getSharedManager()->attach('Api\Controller', 'dispatch', $listener);
}
I have created a base controller Api\Controller
of Zend\Mvc\Controller\AbstractRestfulController
type and then I'll inherit this controller to all other controllers.
ListenerFactory
class AuthenticationListenerFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $sl)
{
$name = 'Api\Adapter\HeaderAuthentication';
$adapter = $sl->get($name);
$listener = new AuthenticationListener($adapter);
return $listener;
}
}
AuthenticationListener
class AuthenticationListener {
protected $adapter;
public function __construct(HeaderAuthentication $adapter) {
$this->adapter = $adapter;
die('died in listener'); // this executes before controller execution.
}
public function __invoke(MvcEvent $event) { // this executes after controller action execution
$result = $this->adapter->authenticate();
die('died in listener');
if(!$result->isValid()){
$response = $event->getResponse();
$response->setStatusCode(400);
$responseMessages = '';
foreach($result->getMessages() as $message) {
$responseMessages .= $message . '. ';
}
$response->setContent($responseMessages);
return $response;
}
$event->setParam('user', $result->getIdentity());
}
}
Okay so what I found is interesting. In ZF2 postDispatch
and preDispatch
behavior can be achieved by prioritizing events. Simply add a priority to your event like this
$em->getSharedManager()->attach('Api\Controller', 'dispatch', $listener, 100);
By default events have a priority of 1
. All events having priority greater than 1
called before action and act as preDispatch
. While a number less than or equal to 1
makes it postDispatch
.
$em->getSharedManager()->attach('Api\Controller', 'dispatch', $listener); // postDispatch
$em->getSharedManager()->attach('Api\Controller', 'dispatch', $listener, 100); // preDispatch
$em->getSharedManager()->attach('Api\Controller', 'dispatch', $listener, -100); // postDispatch