Listeners automatically being attached when using 'listeners' config key

旧城冷巷雨未停 提交于 2019-12-13 03:39:25

问题


I was just setting up a listener aggregate class to respond to certain events. I wanted to be flexible and give myself the possibility to easily turn listeners off and on through the config file.

The ListenerAggregate looks like this (simplified):

LogEventsListener.php:

namespace MyApp\Listener;

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

    /**
     * {@inheritDoc}
     */
    public function attach(EventManagerInterface $events)
    {
        $sharedEvents = $events->getSharedManager();
        $this->listeners[] = $sharedEvents->attach(
                                        'Zend\Mvc\Controller\AbstractActionController', 
                                        'runtime_error', 
                                        array($this, 'onLog'), 
                                        100
        );
    }

    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $listener)
        {
            if ($events->detach($listener))
            {
                unset($this->listeners[$index]);
            }
        }
    }

    public function onLog(EventInterface $e)
    {
        // ... logging code ...
    }
}

In application.config.php I added the listeners array, allowing me to turn the listeners off and on, as there are going to be more listener aggregates in this application:

application.config.php:

return array(
    'listeners' => array(
        'MyApp\Listener\LogEventsListener',
        // ... other listeners to follow ...
    ),
// ... other stuff ...

In my module.config.php for the main application module I added a service_manager entry to allow the listener aggregate to be instantiated:

module.config.php:

'service_manager' => array(
        'invokables' => array(
            'MyApp\Listener\LogEventsListener' => 'MyApp\Listener\LogEventsListener',
        ),
// ... other stuff...

Now in my application module's Module.php onBootstrap method I wanted to load and attach the listeners. Somewhat like this: Module.php:

public function onBootstrap(MvcEvent $e)
{
    $eventManager = $e->getApplication()->getEventManager();
    $sm = $e->getApplication()->getServiceManager();
    $config = $sm->get('config');

    if (array_key_exists('listeners', $config))
    {
        $listeners = $config['listeners'];
        foreach ($userListeners as $curListener)
        {
            $listener = $sm->get($curListener);
            $eventManager->attach($listener);
        }
    }
}

This all works nice and dandy, except that I noticed that the event handler (onLog) was called twice every time the event got triggered.

Further investigation showed that apparently the 'listeners' array in application.config.php is in use by the framework, because they listeners are automatically being instantiated and attached. So when I leave out the code from Module.php to manually attach the listeners they are still being attached.

I couldn't find anything about this behavior in the official documentation and I'm not sure if I can rely on this. Is the 'listeners' key a special key used by ZF2 and is there more information available about this? Can I rely on the fact that listeners in that array will be loaded by the framework in future versions?

来源:https://stackoverflow.com/questions/24897470/listeners-automatically-being-attached-when-using-listeners-config-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!