2014-11-19 2 views
2

В настоящее время у меня есть приложение ZF2, настроенное с помощью «приложения» для одного модуля. Я грузиться приложение Закрепление событие таким образом:События ZF2 для нескольких модулей

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

Теперь мне нужно, чтобы создать новый модуль «API», который должен обрабатывать только URLS начиная domain.com/api (настроить маршрутизатор в «API» файл конфигурации модуля для обработки только таких URL-адресов). Я грузиться «апи» модуль так же, как модуль «приложения», и я придаю специальный случай:

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

Что происходит, что, когда я называю domain.com/application - оба модуля инициализируется и события из обоих модулей запускаются. Мне нужно, чтобы события запускались в зависимости от приложения, которое отправляет действие.

Как я могу это достичь?

ответ

4

В настоящее время вы подключаете прослушивателей событий к диспетчеру событий приложения. Это единственный экземпляр диспетчера событий, который инициирует все события MVC.

Как это экземпляр же не будет никакой разницы, где Вы придаете слушателей; все они будут вызваны независимо.

Вам нужно будет специально проверить в каждом слушателе, если согласованный маршрут является тем, что слушатель должен действовать. Если это не так, выйдите рано.

Например:

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

Так что слушатель будет по-прежнему срабатывает, однако она не будет «делать» что-нибудь.

Вы также можете пойти дальше и предотвратить этот ненужный вызов, специально настроив необходимый менеджер событий, который вас интересует; для этого мы можем использовать SharedEventManager.

При подключении слушателя к SharedEventManager вам необходимо указать «идентификатор» целевого диспетчера событий. Предположим, вы нацелились на «контроллер API».

Так выше будет изменен на

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 
} 
+0

Спасибо Алекс. Первый из них, конечно, будет работать, но мне не нравится этот подход, так как события все еще срабатывают, даже если они не делают ничего, если не нужно. Также он добавляет дополнительную зависимость от имен маршрутов. Второе решение - можно ли связать событие с «Api \\ * \\ *» (подстановочный знак) вместо «Api \ Controller \ Index»? – Joe

+0

Да, вы можете, «идентификатор» может быть любой строкой, которая вам нравится (хотя я бы рекомендовал имя интерфейса, если вы хотите настроить таргетинг на несколько контроллеров). Вам просто нужно убедиться, что каждый менеджер событий в контроллерах имеет этот новый набор идентификаторов (вы можете сделать это в 'setEventManager' или' __construct', используя '$ this-> getEventManager() -> addIdentifiers (['identifier']) 'в абстрактном контроллере или через сервисную фабрику). Ознакомьтесь с разделом ['SharedEventManager' в документации] (https://zf2.readthedocs.org/en/latest/tutorials/tutorial.eventmanager.html#shared-managers). – AlexP

+0

Отлично. Большое спасибо Alex – Joe

Смежные вопросы