2013-04-23 73 views
2

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

我的路线看起来像这样:

模块FBWeb,在URL中的 “应用程序” 模块:

/app/controller/action/par1/val1 

模块FBWsrv,这是在URL “wsrv”:

/wsrv/controller/action/par1/val1 

正如我所说的,路线工作正常。我得到正确的控制器和行动。但问题是MVC事件监听器在两个模块上运行,甚至没有运行/ wsrv路由中的/ app。如果我在/ 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); 

    } 

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); 

    } 

我有securityWsrvDispatch禁用在FBWsrv中,当我测试一些东西时,但我希望它能在以后运行它自己的过程。现在,我只需要分离FBWeb事件,如果我在FBWsrv中运行,因为它们没有相关性。我知道它们都在运行,因为错误出现在相反的模块中。不知道如何做到这一点。

感谢您的帮助!

格雷格

编辑/ NOTES: 我也尝试安装听众之前添加一个简单的检查了NAMESPACE,但似乎这两个命名空间总是叫,这两个模块创建的听众,即使只有一个是需要的。你如何隔离它们? 我想这一点,它不工作:

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

一个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) 
    // ... 

} 

在我的其他模块: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) 
    // ... 

} 

回答

4

你为什么不通过共享事件管理器连接使用方面的活动,有大量的文档在那里与共享活动经理帮助的。

/** 
* 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); 
} 
+0

这是个好主意,Andrew,谢谢!我确实遇到了Evan Coury的帖子[link](http://blog.evan.pro/module-specific-layouts-in-zend-framework-2),这看起来就是你所描述的。我认为这将为我想要的部分工作。但对于其中的一些,我不得不考虑它。阅读他的帖子之前,只是困惑了我。 :)但我认为你提到的只是引发了一个想法,所以我试着去测试...... :)但同时,我可能有一个解决方法,我从罗布艾伦发现:[链接](http:// akrabat.com/zend-framework-2/module-specific-bootstrapping-in-zf2/)我会在上面发表注释。谢谢! – gregthegeek 2013-04-23 23:08:50

+0

好吧,我可以看到这是如何处理这个问题的正确方法。不过,我不确定我的ACL如何在封闭中工作。我需要重写一些我的preDispatch设置,因此它可以与getSharedManager()一起使用,所以我现有的代码还不能工作。尽管将其标记为解决方案。感谢您的时间来帮助我安德鲁! – gregthegeek 2013-04-24 00:00:08

+0

当然你不需要使用闭包,用数组($ object,'method')或'class :: method'等替换闭包:) – Andrew 2013-04-24 07:46:10