Где регистрировать слушателей событий

Я пытаюсь использовать систему событий в CakePHP v2.1 +

Он кажется довольно мощным, но документация несколько расплывчата. Запуск события кажется довольно простым, но я не уверен, как зарегистрировать соответствующих слушателей (слушателей) для прослушивания события. Соответствующий раздел находится здесь, и он предлагает следующий пример кода:

App::uses('CakeEventListener', 'Event'); class UserStatistic implements CakeEventListener { public function implementedEvents() { return array( 'Model.Order.afterPlace' => 'updateBuyStatistic', ); } public function updateBuyStatistic($event) { // Code to update statistics } } // Attach the UserStatistic object to the Order's event manager $statistics = new UserStatistic(); $this->Order->getEventManager()->attach($statistics); 

Но он не говорит, где должен находиться этот код. Внутри конкретного контроллера? Внутри контроллера приложения?

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

Обновление. Это звучит как популярный способ сделать это, поместив регистрационный код слушателя в файл bootstrap.php плагина. Однако я не могу понять, как вызвать getEventManager (), потому что классы контроллера приложения и т. Д. Недоступны.

Обновление 2: Мне также говорят, что слушатели могут жить внутри моделей.

Обновление 3: Наконец-то какая-то тяга! Следующий код успешно зарегистрирует событие, когда внутри MyPlugin / Config / bootstrap.php

 App::uses('CakeEventManager', 'Event'); App::uses('CakeEventListener', 'Event'); class LegacyWsatListener implements CakeEventListener { public function implementedEvents() { return array( 'Controller.Attempt.complete' => 'handleLegacyWsat', ); } public static function handleLegacyWsat($event) { //method must be static if used by global EventManager // Code to update statistics error_log('event from bootstrap'); } } CakeEventManager::instance()->attach(array('LegacyWsatListener', 'handleLegacyWsat'), 'Controller.Attempt.complete'); 

Я не уверен, почему, но я не могу получить ошибки, когда я пытаюсь объединить два App::uses() в одну строку.

Solutions Collecting From Web of "Где регистрировать слушателей событий"

Мероприятия

События – это обратные вызовы, связанные с строкой. Объект, подобный Модели, вызывает событие, использующее строку, даже если ничто не слушает это событие.

CakePHP поставляется с встроенными событиями для таких вещей, как модели. Вы можете присоединить прослушиватель событий к модели и ответить на событие Model.beforeSave .

EventManager

Каждая модель в торте имеет собственный EventManager, плюс есть gobal singleton EventManager. Это не все тот же экземпляр EventManager, и они работают несколько иначе.

Когда модель запускает событие, она делает это с использованием справки EventManager. Это означает, что вы можете присоединить прослушиватель событий к определенной модели. Преимущества заключаются в том, что ваш слушатель будет получать события только от этой модели.

Глобальные слушатели – это те, которые привязаны к экземпляру Singleton EventManager. Который можно получить в любом месте вашего кода. Когда вы присоединяете слушателя там, он вызывается для каждого события, которое происходит независимо от того, кто его запускает.

Когда вы присоединяете прослушиватель событий в bootstrap.php приложения или плагина, вы можете использовать глобальный менеджер, иначе вам нужно получить ссылку на ClassRegistry модель, используя ClassRegistry .

Какой EventManager использовать?

Если событие, которое вы хотите обработать, предназначено для конкретной модели, затем присоедините слушателя к EventManager этой модели. Чтобы получить ссылку на модель, вы можете вызвать ClassRegistry::init(...) .

Если событие, которое вы хотите обработать, может быть запущено в любом месте, затем присоедините слушателя к глобальному EventManager.

Только вы знаете, как ваш слушатель должен использоваться.

Внутри слушателя

Как правило, вы вводите свою бизнес-логику в модели. Вам не нужно получать доступ к контроллеру из прослушивателя событий. Модели намного легче получить доступ и использовать в Cake.

Вот шаблон для создания CakeEventListener. Слушатель отвечает за мониторинг, когда что-то происходит, и затем передает эту информацию вместе с другой моделью. Вы должны разместить свою бизнес-логику для обработки события в моделях.

 <?php App::uses('CakeEventListener', 'Event'); class MyListener implements CakeEventListener { /** * * @var Document The model. */ protected $Document; /** * Constructor */ public function __construct() { // get a reference to a Model that we'll use $this->Document = ClassRegistry::init('Agg.Document'); } /** * Register the handlers. * * @see CakeEventListener::implementedEvents() */ public function implementedEvents() { return array( 'Model.User.afterSave'=>'UserChanged' ); } /** * Use the Event to dispatch the work to a Model. * * @param CakeEvent $event * The event object and data. */ public function UserChanged(CakeEvent $event) { $data = $event->data; $subject = $event->subject(); $this->Document->SomethingImportantHappened($data,$subject); } } 

Мне нравится делать все мои события в папке Lib . Это позволяет легко получить доступ из любого места исходного кода. Вышеприведенный код перейдет в App/Lib/Event/MyListener.php .

Прикрепление EventListeners

Опять же, это зависит от того, какие события вам нужно слушать. Первое, что вам нужно понять, это то, что для запуска события должен быть создан объект.

Например;

Модель Document может Model.beforeSave событие Model.beforeSave когда контроллер Calendar отображает индекс, потому что контроллер Calendar никогда не использует модель Document . Вам нужно добавить слушателя в Document в bootstrap.php чтобы поймать, когда он сэкономит? Нет, если модель Document используется только с контроллера Documents , тогда вам нужно только подключить к нему слушателя.

С другой стороны, модель User используется компонентом Auth почти каждый. Если вы хотите обработать User был удален. Возможно, вам придется подключить прослушиватель событий в bootstrap.php чтобы убедиться, что вы не удалили вас.

В приведенном выше примере мы можем напрямую подключиться к модели User .

 App::uses('MyListener','Lib'); $user = ClassRegistry::init('App.User'); $user->getEventManager()->attach(new MyListener()); 

Эта строка импортирует ваш класс слушателя.

 App::uses('MyListener','Lib'); 

Эта строка получит экземпляр модели пользователя.

 $user = ClassRegistry::init('App.User'); 

Эта строка создает слушатель и присоединяет его к модели пользователя.

 $user->getEventManager()->attach(new MyListener()); 

Если модель User используется во многих разных местах. Возможно, вам придется сделать это в bootstrap.php , но если он используется только одним контроллером. Вы можете разместить этот код в beforeFilter или в верхней части файла PHP.

Что такое Global EventManager?

Предполагая, что нам нужно слушать общие события. Например, когда когда- либо сохраняется какая-либо вещь. Мы хотели бы подключиться к глобальному EventManager. Это будет похоже на что-то подобное и будет помещено в bootstrap.php .

 App::uses('MyListener','Lib'); CakeEventManager::instance()->attach(new MyListener()); 

Если вы хотите подключить прослушиватель событий в файле bootstrap.php вашего плагина, все должно работать нормально, используя подсказки, указанные в ответах. Вот мой код (который работает правильно):

MyPlugin / Config / bootstrap.php:

 App::uses('CakeEventManager', 'Event'); App::uses('MyEventListener', 'MyPlugin.Lib/Event'); CakeEventManager::instance()->attach(new MyEventListener()); 

MyPlugin / Lib / Событие / MyEventListener.php:

 App::uses('CakeEventListener', 'Event'); class MyEventListener implements CakeEventListener { ... } 

Слушатели событий, связанные с MyPlugin, регистрируются только при загрузке плагина. Если я не хочу использовать плагин, прослушиватели событий не подключены. Я думаю, что это чистое решение, если вы хотите добавить некоторые функции в разных местах вашего приложения, используя плагин.

Его «не важно, где находится код. Просто убедитесь, что он выполнен и ваши события зарегистрированы и подключены.

Мы используем один файл, в котором все события подключены и включают его из bootstrap.php, что гарантирует, что все события доступны из всех мест в приложении.

Магия происходит, когда вы отправляете событие, например, из действия контроллера.

 $event = new CakeEvent('Model.Order.afterPlace', $this, array('some'=>'data') )); $this->getEventManager()->dispatch($event); 

Однако вы можете отправлять события из любого места, куда вы можете попасть в EventManager (по умолчанию в моделях, контроллерах и представлениях)