События 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», который должен обрабатывать только URL-адреса, начиная с domain.com/api (я настраиваю маршрутизатор в файле конфигурации модуля «api» для обработки только таких URL-адресов).
Я загружаю модуль «api» так же, как и модуль «application», и прикрепляю выделенное событие:

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 — оба модуля инициализируются и запускаются события из обоих модулей. Мне нужно, чтобы события запускались в зависимости от приложения, которое отправляет действие.

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

2

Решение

В настоящее время вы подключаете прослушиватели событий к менеджеру событий приложения. Это единственный экземпляр менеджера событий, который будет запускать все события 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
}
4

Другие решения

метод 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__);
}
0

По вопросам рекламы [email protected]