0

I have problem with attaching OnDispatch event in Apigility. I want to have value from custom header in constructor of my abstract Service Class. It works when I simply add it to on bootstrap in Module.php

public function onBootstrap(MvcEvent $e)
{
    $eventManager        = $e->getApplication()->getEventManager();
    $moduleRouteListener = new ModuleRouteListener();
    $moduleRouteListener->attach($eventManager);
    $eventManager->attach(\Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this, 'onDispatch'));
}

public function onDispatch(\Zend\Mvc\MvcEvent $e){
    $e->getRequest()->getHeaders()->get('User-Token')->getFieldValue();
}

But I don't know how to pass this value to ServiceAbstract Constructor.

I also tried with implementing EventManagerAwareInterface and attaching events with attachDefaultListeners() method but that didn't get me any results - attached function was not called. What is the proper approach to attaching to events NOT in controllers? Thanks for any help.

4

1 回答 1

1

It seems to me that you have two different goals here.

1. Store a header variable from a route event.

2. Get a variable into the constructor function of a class

To answer 1.

You can make a listener class and attach this class to your eventManager. This would look something like this:

<?php

namespace My\Listener;

use Zend\EventManager\ListenerAggregateInterface;
use Zend\EventManager\EventManagerInterface;
use Zend\Mvc\MvcEvent;
use Zend\Http\Headers;
use Zend\Http\Request as HttpRequest;

class MyCustomListener implements ListenerAggregateInterface
{
    /**
     * @var \Zend\Stdlib\CallbackHandler[]
     */
    protected $listeners = array();

    /**
     * @param EventManagerInterface $eventManager
     */
    public function attach(EventManagerInterface $eventManager)
    {
        // attach on route
        $this->listeners[] = $eventManager->attach(MvcEvent::EVENT_DISPATCH, array($this, 'onDispatch'));
    }

    /**
     * @param EventManagerInterface $eventManager
     */
    public function detach(EventManagerInterface $eventManager)
    {
        foreach ($this->listeners as $index => $listener) {
            if ($eventManager->detach($listener)) {
                unset($this->listeners[$index]);
            }
        }
    }

    /**
     * Do your thing on dispatch event with your headers
     *
     * @param MvcEvent $event
     */
    public function onDispatch(MvcEvent $event)
    {
        $request = $event->getRequest();
        if(!$request instanceof HttpRequest){
            // Nothing to do
            return;
        }

        $headers = $request->getHeaders();

        // You could for example get a service here and store your value
    }
}

You attach this listener in Module.php like this:

public function onBootstrap(MvcEvent $event)
{
    $event->getApplication();
    $application->getEventManager();
    $eventManager->attach($serviceManager->get('My\Listener\MyCustomListener'));
}

You have to register your listener in your ServiceManager either under invokables or factories with the key My\Listener\MyCustomListener to be able to attach it here like this.

To answer 2:

To get a variable in your constructor you can make a factory for your class and get the variable from the service that holds the variable that you need (could be from the listener from 1 directly).

<?php
namespace My\Factory;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use My\Folder\MyCustomClass;

class MyClassFactory implements FactoryInterface
{
    /**
     * @param  ServiceLocatorInterface $serviceLocator
     * @return Logger
     */
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $controllerPluginManager = $serviceLocator;
        $service = $serviceManager->get(My\Service\MyStorageService);
        $dependency = $service->getDependency();
        return new MyCustomClass($dependency);
    }
}
于 2015-05-04T14:37:02.320 回答