diff --git a/docs/guide-ru/concept-events.md b/docs/guide-ru/concept-events.md index e008e64980..429367e779 100644 --- a/docs/guide-ru/concept-events.md +++ b/docs/guide-ru/concept-events.md @@ -225,61 +225,70 @@ Event::off(Foo::className(), Foo::EVENT_HELLO); Обработчики событий на уровне интерфейсов ------------- -Еще более общим случаем, чем обработка событий на уровне класса, является обработка на уровнне *интерфейсов*. Для этого по аналогии с обработчиками событий на уровне классов, необходимо вызвать статический метод [[yii\base\Event::on()]], передав ему в качестве первого параметра имя интерфейса. В этом случае инициализация события для любого класса, реализующего указанный интерфейс, будет приводить к срабатыванию соответствующего обработчика. +Существует еще более абстрактный способ обработки событий. +Вы можете создать отдельный интерфейс для общего события и реализовать его в классах, где это необходимо. -Например, имеется следующий интерфейс: +Например, создадим следующий интерфейс: ```php -interface MyInterface +interface DanceEventInterface { - const EVENT_HELLO = 'hello'; + const EVENT_DANCE = 'dance'; } ``` -И классы: +И два класса, которые его реализовывают: ```php -class MyClass1 extends Component implements MyInterface +class Dog extends Component implements DanceEventInterface { - public function myFunction() + public function meetBuddy() { - $this->trigger(MyInterface::EVENT_HELLO); + echo "Woof!"; + $this->trigger(DanceEventInterface::EVENT_DANCE); } } -class MyClass2 extends Component implements MyInterface +class Developer extends Component implements DanceEventInterface { - public function myFunction() + public function testsPassed() { - $this->trigger(MyInterface::EVENT_HELLO); + echo "Yay!"; + $this->trigger(DanceEventInterface::EVENT_DANCE); } } ``` -В этом случае, для того, чтобы подписаться на события в любом из классов `MyClass1` или `MyClass2` достаточно добавить следующий код: +Для обработки события `EVENT_DANCE`, инициализированного любым из этих классов, +вызовите [[yii\base\Event::on()|Event:on()]], передав ему в качестве первого параметра имя интерфейса. ```php -Event::on('MyInterface', MyInterface::EVENT_HELLO, function ($event) { - echo $event->sender; // Выводит MyClass1 или MyClass2 в зависимости от класса, вызвавшего событие -}) +Event::on('DanceEventInterface', DanceEventInterface::EVENT_DANCE, function ($event) { + Yii::trace($event->sender->className . ' just danced'); // Оставит запись в журнале о том, что кто-то танцевал +}); ``` -Обратите внимание, что в отличие от событий на *уровне класса*, для событий на *уровне интерфейса* статический вызов метода [[yii\base\Event::trigger()]] невозможен: +Вы можете также инициализировать эти события: ```php -Event::trigger('MyInterface', MyInterface::EVENT_HELLO); // Приведет к ошибке - -Event::trigger(MyClass1::className(), MyInterface::EVENT_HELLO); // Корректная запись, обработчик будет вызван +Event::trigger(DanceEventInterface::className(), DanceEventInterface::EVENT_DANCE); ``` -Отсоединить обработчик события на уровне класса можно с помощью метода [[yii\base\Event::off()]]. Например: +Однако, невозможно инициализировать событие во всех классах, которые реализуют интерфейс: ```php -// отсоединение $handler -Event::off('MyInterface', MyInterface::EVENT_HELLO, $handler); +// НЕ БУДЕТ РАБОТАТЬ +Event::trigger('DanceEventInterface', DanceEventInterface::EVENT_DANCE); // ошибка +``` -// отсоединяются все обработчики MyInterface::EVENT_HELLO -Event::off('MyInterface', MyInterface::EVENT_HELLO); +Отсоединить обработчик события можно с помощью метода [[yii\base\Event::off()|Event::off()]]. Например: + +```php +// отсоединяет $handler +Event::off('DanceEventInterface', DanceEventInterface::EVENT_DANCE, $handler); + +// отсоединяются все обработчики DanceEventInterface::EVENT_DANCE +Event::off('DanceEventInterface', DanceEventInterface::EVENT_DANCE); ``` Глобальные события diff --git a/docs/guide/concept-events.md b/docs/guide/concept-events.md index 0ba9ac3703..205c99b169 100644 --- a/docs/guide/concept-events.md +++ b/docs/guide/concept-events.md @@ -252,6 +252,76 @@ Event::off(Foo::className(), Foo::EVENT_HELLO); ``` +Events using interfaces +------------- + +There is even more abstract way to deal with events. You can create a separated interface for the special event and +implement it in classes, where you need it. + +For example we can create the following interface: + +```php +interface DanceEventInterface +{ + const EVENT_DANCE = 'dance'; +} +``` + +And two classes, that implement it: + +```php +class Dog extends Component implements DanceEventInterface +{ + public function meetBuddy() + { + echo "Woof!"; + $this->trigger(DanceEventInterface::EVENT_DANCE); + } +} + +class Developer extends Component implements DanceEventInterface +{ + public function testsPassed() + { + echo "Yay!"; + $this->trigger(DanceEventInterface::EVENT_DANCE); + } +} +``` + +To handle the `EVENT_DANCE`, triggered by any of these classes, call [[yii\base\Event::on()|Event::on()]] and +pass the interface name as the first argument: + +```php +Event::on('DanceEventInterface', DanceEventInterface::EVENT_DANCE, function ($event) { + Yii::trace($event->sender->className . ' just danced'); // Will log that Dog or Developer danced +}) +``` + +You can trigger the event of those classes: + +```php +Event::trigger(DanceEventInterface::className(), DanceEventInterface::EVENT_DANCE); +``` + +But please notice, that you can not trigger all the classes, that implement the interface: + +```php +// DOES NOT WORK +Event::trigger('DanceEventInterface', DanceEventInterface::EVENT_DANCE); // error +``` + +Do detach event handler, call [[yii\base\Event::off()|Event::off()]]. For example: + +```php +// detaches $handler +Event::off('DanceEventInterface', DanceEventInterface::EVENT_DANCE, $handler); + +// detaches all handlers of DanceEventInterface::EVENT_DANCE +Event::off('DanceEventInterface', DanceEventInterface::EVENT_DANCE); +``` + + Global Events ------------- @@ -278,4 +348,4 @@ which will be triggered by the object. Instead, the handler attachment and the e done through the Singleton (e.g. the application instance). However, because the namespace of the global events is shared by all parties, you should name the global events -wisely, such as introducing some sort of namespace (e.g. "frontend.mail.sent", "backend.mail.sent"). +wisely, such as introducing some sort of namespace (e.g. "frontend.mail.sent", "backend.mail.sent"). \ No newline at end of file