События ( Events )

Использование

Класс Event содержит простую реализацию концепции Observer ("Наблюдатель"), что позволяет Вам подписываться на уведомления о событиях (listen for events) в вашем приложении. Пример:

Event::listen('auth.login', function($user) {
    $user->last_login = new DateTime;
    $user->save();
});

Вы можете получить доступ к этому событию при помощи метода Event::fire, который позволяет расширить логику Вашего приложения:

Event::fire('auth.login', [$user]);

Подписка на события

Вы можете использовать метод Event::listen в любом месте. Первый аргумент - название события.

Event::listen('acme.blog.myevent', ...);

Второй аргумент - функция-замыкание с произвольными аргументами.

Event::listen('acme.blog.myevent', function($arg1, $arg2) {
    // Do something
});

Вы также можете передать ссылку на вызываемый объект или на класс.

Event::listen('auth.login', [$this, 'LoginHandler']);

Примечание: Вы можете указать все аргументы, их часть или ничего. В любом случае событие не будет вызывать никаких ошибок, если их не указано слишком много.

Где писать код ?

Наиболее подходящее место - метод boot в файле регистрации плагина.

class Plugin extends PluginBase
{
    [...]

    public function boot()
    {
        Event::listen(...);
    }
}

Вы также можете использовать файл init.php в папке с плагином. Пример:

<?php

Event::listen(...);

Подписка на событие с приоритетом

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

// Run first
Event::listen('auth.login', function() { ... }, 10);

// Run second
Event::listen('auth.login', function() { ... }, 5);

Прерывание обработки события

Иногда Вам может быть нужно пропустить вызовы других обработчиков события. Вы можете сделать это, вернув значение false:

Event::listen('auth.login', function($event) {
    // Handle the event

    return false;
});

Обработчики по шаблону (wildcard)

Вы можете использовать звёздочки (*) при регистрации обработчика для привязки его ко всем подходящим событиям. Пример:

Event::listen('foo.*', function($param) {
    // Handle the event...
});

Используйте метод Event::firing, для определения того, какое именно событие из подходящих под foo.* поймано:

Event::listen('foo.*', function($param) {
    if (Event::firing() == 'foo.bar') {
        // ...
    }
});

Вызов событий ( Firing events )

Вы можете использовать метод Event::fire в любом месте вашего кода, чтобы сделать логику расширяемой. Это означает, что другие разработчики или даже Ваш собственный код могут «подключиться» к этой точке и добавить новую логику. Первый аргумент - название события.

Event::fire('myevent')

Вы можете использовать в качестве префикса пространство имен, чтобы избежать конфликты с другими плагинами.

Event::fire('acme.blog.myevent');

Второй аргумент - произвольный массив данных, которые будут использоваться в качестве аргументов в методе Event::listen.

Event::fire('acme.blog.myevent', [$arg1, $arg2]);

Третий аргумент указывает на то, что событие должно прерываться, если возвращаемое значение - "non null". По умолчанию этот аргумент имеет значение false.

Event::fire('acme.blog.myevent', [...], true);

// Single result, event halted
$result = Event::fire('acme.blog.myevent', [...], true);

// Collection of results, all events fired
$results = Event::fire('acme.blog.myevent', [...]);

Передача аргументов по ссылке

Вы можете передать переменную по ссылке, чтобы изменить ее содержимое:

// $content = '111'
Event::fire('cms.processContent', [&$content]);

Пример:

Event::listen('cms.processContent', function (&$content) {
    $content = $content . 'A';
});

Event::listen('cms.processContent', function (&$content) {
    $content = $content . 'B';
});

В итоге: $content = '111AB'.

Очередь событий

Вы можете использовать метод Event::queue, чтобы отложить выполнение события и добавить его в очередь.

Event::queue('foo', [$user]);

Используйте метод Event::flush, чтобы удалить все события из очереди.

Event::flush('foo');

Использование классов в качестве слушателей

Вы можете использовать классы для обработки событий.

Определение метода-подписчика

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

Event::listen('auth.login', 'LoginHandler');

По умолчанию буде вызываться метод handle класса LoginHandler:

class LoginHandler
{
    public function handle($data)
    {
        // ...
    }
}

Вы можете заменить этот метода на любой другой:

Event::listen('auth.login', 'LoginHandler@onLogin');

Определение класса-подписчика

Подписчики на события (Event Class Subscribers) - классы, которые могут быть подписаны на несколько событий и содержать сразу несколько обработчиков событий. Такой класс должен иметь метод subscribe, который принимает в аргументах инстанс диспетчера событий:

class UserEventHandler
{
    /**
     * Handle user login events.
     */
    public function userLogin($event)
    {
        // ...
    }

    /**
     * Handle user logout events.
     */
    public function userLogout($event)
    {
        // ...
    }

    /**
     * Register the listeners for the subscriber.
     *
     * @param  Illuminate\Events\Dispatcher  $events
     * @return array
     */
    public function subscribe($events)
    {
        $events->listen('auth.login', 'UserEventHandler@userLogin');

        $events->listen('auth.logout', 'UserEventHandler@userLogout');
    }
}

После того как класс определён, его можно зарегистрировать следующим образом:

Event::subscribe(new UserEventHandler);

Вы также можете использовать сервис-контейнер для того, чтобы получить объект своего подписчика на события:

Event::subscribe('UserEventHandler');

Трейт

Вы можете использовать трейт October\Rain\Support\Traits\Emitter, чтобы связать события с экземпляром объекта внутри вашего класса.

class UserManager
{
    use \October\Rain\Support\Traits\Emitter;
}

Этот трейт позволяет "слушать" события при помощи метода bindEvent.

$manager = new UserManager;
$manager->bindEvent('user.beforeRegister', function($user) {
    // Check if the $user is a spammer
});

Метод fireEvent используется для «выстреливания» события.

$manager = new UserManager;
$manager->fireEvent('user.beforeRegister', [$user]);

Эти события будут происходить только для локального объекта.