Статьи

Пользовательские события в Laravel

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

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

Например, скажем, вы хотите уведомить все модули в системе, когда кто-то заходит на ваш сайт. Таким образом, он позволяет им реагировать на это событие входа в систему, независимо от того, идет ли речь об отправке электронного письма или уведомления в приложении, или, в этом отношении, обо всем, что хочет отреагировать на это событие входа в систему.

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

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

Идите вперед и извлеките файл app/Providers/EventServiceProvider.php .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        ‘App\Events\SomeEvent’ => [
        ‘App\Listeners\EventListener’,
        ],
    ];
    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
        //
    }
}

Давайте внимательно посмотрим на свойство $listen , которое позволяет вам определять массив событий и связанных слушателей. Ключи массива соответствуют событиям в системе, а их значения соответствуют слушателям, которые будут срабатывать при возникновении соответствующего события в системе.

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

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

На самом деле, вам повезло, так как Laravel помогает вам решить эту проблему с помощью прослушивателя событий. Давайте app/Providers/EventServiceProvider.php файл app/Providers/EventServiceProvider.php чтобы он выглядел следующим образом.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        ‘Illuminate\Auth\Events\Login’ => [
        ‘App\Listeners\SendEmailNotification’,
        ],
    ];
    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
        //
    }
}

Illuminate\Auth\Events\Login — это событие, которое вызывается плагином Auth когда кто-то входит в приложение. Мы связали это событие с прослушивателем App\Listeners\SendEmailNotification , поэтому оно будет вызвано событием входа в систему.

Конечно, вам нужно определить класс слушателя App\Listeners\SendEmailNotification в первую очередь. Как всегда, Laravel позволяет создавать шаблон кода слушателя с помощью команды artisan.

1
php artisan event:generate

Эта команда генерирует классы событий и слушателей, перечисленные в свойстве $listen .

В нашем случае событие Illuminate\Auth\Events\Login уже существует, поэтому оно создает только класс прослушивателя App\Listeners\SendEmailNotification . Фактически, он также создал бы класс событий Illuminate\Auth\Events\Login если бы он не существовал в первую очередь.

Давайте посмотрим на класс слушателя, созданный в app/Listeners/SendEmailNotification.php .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
namespace App\Listeners;
use Illuminate\Auth\Events\Login;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendEmailNotification
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    /**
     * Handle the event.
     *
     * @param Login $event
     * @return void
     */
    public function handle(Login $event)
    {
         
    }
}

Это метод handle который будет вызываться с соответствующими зависимостями при каждом запуске слушателя. В нашем случае аргумент $event должен содержать контекстную информацию о событии входа в систему — зарегистрированную информацию о пользователе.

И мы можем использовать объект $event для выполнения дальнейшей обработки в методе handle . В нашем случае мы хотим отправить уведомление по электронной почте зарегистрированному пользователю.

Пересмотренный метод handle может выглядеть примерно так:

1
2
3
4
5
6
7
8
public function handle(Login $event)
{
    // get logged in user’s email and username
    $email = $event->user->email;
    $username = $event->user->name;
     
    // send email notification about login
}

Вот как вы должны использовать функцию событий в Laravel. В следующем разделе мы продолжим создание пользовательского события и связанного с ним класса слушателя.

Пример сценария, который мы собираемся использовать для нашего примера, выглядит примерно так:

  • Приложение должно очищать кеши в системе в определенные моменты. Мы будем вызывать событие CacheClear вместе с контекстной информацией, когда приложение сделает вышеупомянутое. Мы передадим ключи группы кеша вместе с событием, которое было очищено.
  • Другие модули в системе могут прослушивать событие CacheClear и хотели бы реализовать код, который нагревает связанные кэши.

Давайте app/Providers/EventServiceProvider.php файлу app/Providers/EventServiceProvider.php и зарегистрируем наши пользовательские сопоставления событий и слушателей.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        ‘App\Events\ClearCache’ => [
        ‘App\Listeners\WarmUpCache’,
        ],
    ];
    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
        //
    }
}

Как видите, мы определили событие App\Events\ClearCache и связанный с ним класс слушателя App\Listeners\WarmUpCache в свойстве $listen .

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

1
php artisan event:generate

Это должно было создать класс событий в app/Events/ClearCache.php и класс слушателя в app/Listeners/WarmUpCache.php .

С некоторыми изменениями класс app/Events/ClearCache.php должен выглядеть следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class ClearCache
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
     
    public $cache_keys = [];
    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(Array $cache_keys)
    {
        $this->cache_keys = $cache_keys;
    }
    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel(‘channel-name’);
    }
}

Как вы, наверное, заметили, мы добавили новое свойство $cache_keys которое будет использоваться для хранения информации, которая будет передаваться вместе с событием. В нашем случае мы передадим очищенные группы кэша.

Далее, давайте посмотрим на класс слушателя с обновленным методом handle в app/Listeners/WarmUpCache.php .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
namespace App\Listeners;
use App\Events\ClearCache;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class WarmUpCache
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    /**
     * Handle the event.
     *
     * @param ClearCache $event
     * @return void
     */
    public function handle(ClearCache $event)
    {
        if (isset($event->cache_keys) && count($event->cache_keys)) {
            foreach ($event->cache_keys as $cache_key) {
                // generate cache for this key
                // warm_up_cache($cache_key)
            }
        }
    }
}

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

Далее, это просто вопрос итерации каждого ключа кеша и прогрева связанных кешей.

Теперь у нас есть все для проверки. Давайте быстро создадим файл контроллера в app/Http/Controllers/EventController.php чтобы продемонстрировать, как вы можете вызвать событие.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Library\Services\Contracts\CustomServiceInterface;
use App\Post;
use Illuminate\Support\Facades\Gate;
use App\Events\ClearCache;
class EventController extends Controller
{
    public function index()
    {
        // …
         
        // you clear specific caches at this stage
        $arr_caches = [‘categories’, ‘products’];
         
        // want to raise ClearCache event
        event(new ClearCache($arr_caches));
         
        // …
    }
}

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

Функция помощника по событиям используется для вызова события из любого места в приложении. Когда событие поднято, Laravel вызывает всех слушателей, слушающих это конкретное событие.

В нашем случае прослушиватель App\Listeners\WarmUpCache настроен на прослушивание App\Events\ClearCache . Таким образом, метод App\Listeners\WarmUpCache прослушивателя App\Listeners\WarmUpCache вызывается, когда событие вызывается из контроллера. Остальное — разогреть кеши, которые были очищены!

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

Подписчик на событие позволяет вам подписать несколько слушателей событий в одном месте. Независимо от того, хотите ли вы логически сгруппировать прослушиватели событий или хранить растущие события в одном месте, вы ищете именно подписчика событий.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php
// app/Listeners/ExampleEventSubscriber.php
namespace App\Listeners;
class ExampleEventSubscriber
{
    /**
     * Handle user login events.
     */
    public function sendEmailNotification($event) {
        // get logged in username
        $email = $event->user->email;
        $username = $event->user->name;
         
        // send email notification about login…
    }
    /**
     * Handle user logout events.
     */
    public function warmUpCache($event) {
        if (isset($event->cache_keys) && count($event->cache_keys)) {
            foreach ($event->cache_keys as $cache_key) {
                // generate cache for this key
                // warm_up_cache($cache_key)
            }
        }
    }
    /**
     * Register the listeners for the subscriber.
     *
     * @param Illuminate\Events\Dispatcher $events
     */
    public function subscribe($events)
    {
        $events->listen(
            ‘Illuminate\Auth\Events\Login’,
            ‘App\Listeners\ExampleEventSubscriber@sendEmailNotification’
        );
         
        $events->listen(
            ‘App\Events\ClearCache’,
            ‘App\Listeners\ExampleEventSubscriber@warmUpCache’
        );
    }
}

Это метод subscribe который отвечает за регистрацию слушателей. Первый аргумент метода subscribe — это экземпляр класса Illuminate\Events\Dispatcher , который можно использовать для привязки событий к слушателям с помощью метода listen .

Первый аргумент метода listen — это событие, которое вы хотите прослушать, а второй аргумент — это слушатель, который будет вызываться при возникновении события.

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

Класс подписчика события не будет выбран автоматически. Вам необходимо зарегистрировать его в классе EventServiceProvider.php в EventServiceProvider.php $subscriber , как показано в следующем фрагменте.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
    /**
     * The subscriber classes to register.
     *
     * @var array
     */
    protected $subscribe = [
        ‘App\Listeners\ExampleEventSubscriber’,
    ];
    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
        //
    }
}

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

Сегодня мы обсудили несколько интересных особенностей Laravel — события и слушателей. Они основаны на шаблоне проектирования наблюдателя, который позволяет вам вызывать события всего приложения и позволяет другим модулям прослушивать эти события и реагировать соответствующим образом.

Просто освоиться в Laravel или хотите расширить свои знания, сайт или приложение с помощью расширений? У нас есть множество вещей, которые вы можете изучать на Envato Market .

Не стесняйтесь выражать свои мысли, используя канал ниже!