Zend Framework 2如何在多个MVC模块中禁用事件侦听器

gre*_*eek 2 model-view-controller module zend-framework2

我有两个我正在尝试构建的MVC模块,一个(FBWsrv)具有JSON输出和不同的安全过程,以及用于正常Web使用的主MVC模块(FBWeb).我有所有设置的路线,大多数工作.我遇到的问题是他们都有onBootstrap方法附加他们自己的事件监听器,我想如果不在正确的MVC模块中则禁用监听器.

我的路线看起来像这样:

模块FBWeb,url中的"app"模块:

/app/controller/action/par1/val1
Run Code Online (Sandbox Code Playgroud)

模块FBWsrv,在url中是"wsrv":

/wsrv/controller/action/par1/val1
Run Code Online (Sandbox Code Playgroud)

正如我所提到的,路线工作正常.我得到了正确的控制器和动作.但问题是当我甚至没有从/ wsrv路由运行/ app时,MVC事件监听器正在两个模块上运行.如果我在/ wsrv中,我想要做的是禁用/ app中的事件.

模块的简短版本设置如下:

FBWeb/Module.php:

class Module 
{

    public function onBootstrap(MvcEvent $e)
    {

        $this->sm = $application->getServiceManager();
        $this->config = $e->getApplication()->getConfig();

        $eventManager        = $e->getApplication()->getEventManager();
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);

        $eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this, 'addInstanceObjects'), 5000 );
        $eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this, 'securityDispatch'), 0 );
        $eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this, 'preDispatch'), 100 );
        $eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this, 'postDispatch'), -100 );
        $eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH_ERROR, array($this, 'onDispatchError'), -5000);

    }
Run Code Online (Sandbox Code Playgroud)

FBWsrv/Module.php:

class Module 
{
    public function onBootstrap(MvcEvent $e)
    {

        $this->sm = $application->getServiceManager();
        $this->config = $e->getApplication()->getConfig();
        $eventManager        = $e->getApplication()->getEventManager();
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);

        $eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this, 'addWsrvInstanceObjects'), 5900 );
        //$eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this, 'securityWsrvDispatch'), 5800 );
        $eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this, 'preWsrvDispatch'), 5500 );
        $eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this, 'postWsrvDispatch'), 5400 );
        $eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH_ERROR, array($this, 'onWsrvDispatchError'), 5100);

    }
Run Code Online (Sandbox Code Playgroud)

我在测试时已经在FBWsrv中禁用了securityWsrvDispatch,但我希望它稍后运行自己的进程.现在,如果我在FBWsrv中运行,我只需要分离FBWeb事件,因为它们没有相关性.我知道它们都在运行,因为错误出现在相反的模块中.不知道该怎么做.

谢谢你的帮助!

格雷格

编辑/注意:我还尝试在附加侦听器之前添加对NAMESPACE的简单检查,但似乎总是调用两个命名空间,这会为两个模块创建侦听器,即使只需要一个也是如此.你是如何孤立他们的?我试过这个,这不起作用:

if(__NAMESPACE__ == 'FBWeb'){
            $eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this, 'addInstanceObjects'), 5000 );
         ...
Run Code Online (Sandbox Code Playgroud)

A var_dump(__NAMESPACE__);始终显示打印的两个命名空间.

编辑 - 一点解决方法

首先,感谢安德鲁,你引发了一些想法,我将参与该项目.但是,在我学习的过程中,我通过检查路径解决了我的主要问题,然后只是在功能不匹配时从函数返回,跳过模块中的任何其他设置.

我还整理了我的调度事件,这减轻了我的困惑.真的没有任何需要额外的混乱.我知道这不是正确的方法,但确实解决了我的问题.

(当然,您必须设置名为'fbweb'和'fbwsrv'的路径才能匹配您的模块)

在FBWeb/Module.php中:

// in FBWeb/Module.php
// (default web MVC module)

public function onBootstrap(MvcEvent $e)
{
    // ... get eventmanager ...

    $eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this, 'preDispatch'), 1000 );
    $eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH_ERROR, array($this, 'onDispatchError'), -5000);

}

public function preDispatch(MvcEvent $e)
{
    $this->route = $e->getRouteMatch();
    $this->matchedRouteName = explode('/', $this->route->getMatchedRouteName());
    $this->route_root = $this->matchedRouteName[0];

    // then just test if not in correct route
    if($this->route_root != 'fbweb'){
        // if NOT, bail here, 
        // and skip any other setup in this module dispatch
        return;
    }

    // continue other normal stuff (ACL's, session stuff, etc)
    // ...

}
Run Code Online (Sandbox Code Playgroud)

在我的其他模块中:FBWsrv/Module.php:

// in FBWsrv/Module.php

public function onBootstrap(MvcEvent $e)
{
    // ... get eventmanager ...

    $eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this, 'preDispatch'), 5500 );
    $eventManager->attach( \Zend\Mvc\MvcEvent::EVENT_DISPATCH_ERROR, array($this, 'onDispatchError'), -4900);

}

public function preDispatch(MvcEvent $e)
{
    $this->route = $e->getRouteMatch();
    $this->matchedRouteName = explode('/', $this->route->getMatchedRouteName());
    $this->route_root = $this->matchedRouteName[0];
    // then just test if not in correct route
    if($this->route_root != 'fbwsrv'){
        // if NOT, bail here, 
        // and skip any other setup in this module dispatch
        return;
    }

    // continue other normal stuff (ACL's, session stuff, etc)
    // ...

}
Run Code Online (Sandbox Code Playgroud)

And*_*rew 5

为什么不通过共享事件管理器使用上下文附加事件,有很多文档可以帮助共享事件管理器.

/**
 * On bootstrap event
 * 
 * @param \Zend\Mvc\MvcEvent $e
 */
public function onBootstrap(MvcEvent $e)
{
    // .. other stuff

    /**
     * Example attaching events with shared manager, using context
     */
    $e->getApplication()->getEventManager()->getSharedManager()
        ->attach('MyModule\Controller\AbstractActionController', 'dispatch', function($e) {

        // do something to only be triggerd when dispatch is triggered
        // on a controller extending your nice base controller in this module..

    }, 100);
}
Run Code Online (Sandbox Code Playgroud)