简体   繁体   English

多个模块的ZF2事件

[英]ZF2 events for multiple modules

Currently I have an ZF2 application configured with the single module "application". 目前,我有一个配置有单个模块“应用程序”的ZF2应用程序。 I bootstrap the application an attach an event this way: 我以这种方式引导应用程序附加事件:

namespace Application;

use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;

class Module
{
    public function onBootstrap( MvcEvent $e)
    {
        $eventManager        = $e->getApplication()->getEventManager();
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach( $eventManager);

        $this->initTracking( $e);
    }

    /**
     * Initialises user tracking check
     * @param MvcEvent $e
     */
    public function initTracking( MvcEvent $e) 
    {
        $eventManager = $e->getApplication()->getEventManager();
        $eventManager->attach( 'dispatch', function( $e){ 
            $objTracking = new \Application\Event\Tracking( $e);
        }, 200);
    }
}

Now I need to create a new module "api", which should process only urls starting domain.com/api (I configure the router in "api" module config file to handle only such urls). 现在,我需要创建一个新模块“ api”,该模块应仅处理以domain.com/api开头的网址(我在“ api”模块配置文件中将路由器配置为仅处理此类网址)。 I bootstrap the "api" module the same way as "application" module, and I attach a dedicated event: 我以与“应用程序”模块相同的方式引导“ api”模块,并附加一个专用事件:

namespace Api;

use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;

class Module
{
    public function onBootstrap( MvcEvent $e)
    {
        $eventManager        = $e->getApplication()->getEventManager();
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach( $eventManager);

        $this->initLogging( $e);
    }

    /**
     * Initialises loggging
     * @param MvcEvent $e
     */
    public function initLogging( MvcEvent $e) 
    {
        $eventManager = $e->getApplication()->getEventManager();
        $eventManager->attach( 'dispatch', function( $e){ 
            $objLogger = new \Application\Event\Logging( $e);
        }, 200);
    }
}

What happens is that when I call domain.com/application - both modules are being initialised and events from both modules are being triggered. 发生的是,当我调用domain.com/application时-两个模块都正在初始化,并且两个模块中的事件都被触发。 I need events to be triggered depending on the application which is dispatching the action. 我需要根据调度操作的应用程序来触发事件。

How can I achieve that? 我该如何实现?

You are currently attaching the event listeners to the application event manager. 您当前正在将事件侦听器附加到应用程序事件管理器。 This is a single event manager instance that will trigger all MVC events. 这是一个将触发所有MVC事件的事件管理器实例。

As it is the same instance it will make no difference where you attach the listeners; 因为是同一实例,所以附加侦听器的位置没有任何区别; they will all be triggered regardless. 它们都会被触发。

You will need to specifically check, in each listener, if the matched route is one that the listener should action. 您将需要在每个侦听器中专门检查匹配的路由是否是侦听器应采取的措施。 If it is not then exit out early. 如果不是,那就早退。

For example: 例如:

public function onBootstrap(MvcEvent $event)
{
    $eventManager = $event->getApplication()->getEventManager();

    // There is no need to pass in the event 
    // to a seperate function as we can just attach 'initLogging' here
    // as the event listener
    $eventManager->attach('dispatch', array($this, 'initLogging'), 200);
}

// initLogging listener
public function initLogging(MvcEvent $event)
{
    //... check the route is one you want
    // this is quite basic to you might need to edit to
    // suit your specific needs 
    $routeName = $event->getRouteMatch()->getMatchedRouteName();

    if (false === strpos($routeName, 'api')) {
        // we are not an api route so exit early
        return;
    }
    $objLogger = new \Application\Event\Logging($event);
}

So the listener will still be triggered, however it won't 'do' anything. 因此,侦听器仍将被触发,但是不会“做任何事”。

You can however go further and prevent this unnecessary call by specifically targeting the required event manager that you are interested in; 但是,您可以通过专门针对您感兴趣的所需事件管理器来进一步避免这种不必要的调用; to do so we can use the SharedEventManager . 为此,我们可以使用SharedEventManager

When attaching the listener to the SharedEventManager you need to provide an 'identifier' of the target event manager - I'll assume you are targeting a 'API controller'. 将侦听器附加到SharedEventManager您需要提供目标事件管理器的“标识符”-我假设您的目标是“ API控制器”。

So the above would be changed to 因此,以上内容将更改为

public function onBootstrap(MvcEvent $event)
{
    $application = $event->getApplication();
    $sharedEventManager = $application->getEventManager()
                                      ->getSharedManager();

    // The shared event manager takes one additional argument,
    // 'Api\Controller\Index' is our target identifier
    $eventManager->attach('Api\Controller\Index', 'dispatch', array($this, 'initLogging'), 200);
}

// initLogging listener
public function initLogging(MvcEvent $event)
{
    // ... same bits we had before
}

the onDispatch method will be run in only one module onDispatch方法将仅在一个模块中运行

namespace Application;

use Zend\Http\PhpEnvironment\Request;
use Zend\Http\PhpEnvironment\Response;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Zend\ModuleManager\ModuleManagerInterface;
use Zend\Mvc\MvcEvent;

/**
 * @method Request getRequest()
 * @method Response getResponse()
 */
class Module implements ConfigProviderInterface
{
    public function getConfig()
    {
        return array_merge(
            require __DIR__ . '/../config/module.config.php',
            require __DIR__ . '/../config/router.config.php'
        );
    }

    public function init(ModuleManagerInterface $manager)
    {
        $eventManager = $manager->getEventManager();
        // Register the event listener method.
        $sharedEventManager = $eventManager->getSharedManager();
        $sharedEventManager->attach(__NAMESPACE__, MvcEvent::EVENT_DISPATCH,
                                     [$this, 'onDispatch'], 100);
    }

    public function onDispatch(MvcEvent $e)
    {
        var_dump(__METHOD__);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM