1. Code
  2. PHP
  3. Laravel

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

Scroll to top

Russian (Pусский) translation by Ilya Nikov (you can also view the original English article)

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

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

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

Основы событий и слушателей

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

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

Идем дальше и рассмотрим файл app/Providers/EventServiceProvider.php.

1
<?php
2
namespace App\Providers;
3
use Illuminate\Support\Facades\Event;
4
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
5
class EventServiceProvider extends ServiceProvider
6
{
7
    /**

8
     * The event listener mappings for the application.

9
     *

10
     * @var array

11
     */
12
    protected $listen = [
13
        'App\Events\SomeEvent' => [
14
        'App\Listeners\EventListener',
15
        ],
16
    ];
17
    /**

18
     * Register any events for your application.

19
     *

20
     * @return void

21
     */
22
    public function boot()
23
    {
24
        parent::boot();
25
        //

26
    }
27
}

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

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

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

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

1
<?php
2
namespace App\Providers;
3
use Illuminate\Support\Facades\Event;
4
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
5
class EventServiceProvider extends ServiceProvider
6
{
7
    /**

8
     * The event listener mappings for the application.

9
     *

10
     * @var array

11
     */
12
    protected $listen = [
13
        'Illuminate\Auth\Events\Login' => [
14
        'App\Listeners\SendEmailNotification',
15
        ],
16
    ];
17
    /**

18
     * Register any events for your application.

19
     *

20
     * @return void

21
     */
22
    public function boot()
23
    {
24
        parent::boot();
25
        //

26
    }
27
}

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.

1
<?php
2
namespace App\Listeners;
3
use Illuminate\Auth\Events\Login;
4
use Illuminate\Queue\InteractsWithQueue;
5
use Illuminate\Contracts\Queue\ShouldQueue;
6
class SendEmailNotification
7
{
8
    /**

9
     * Create the event listener.

10
     *

11
     * @return void

12
     */
13
    public function __construct()
14
    {
15
        //

16
    }
17
    /**

18
     * Handle the event.

19
     *

20
     * @param  Login  $event

21
     * @return void

22
     */
23
    public function handle(Login $event)
24
    {
25
        
26
    }
27
}

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

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

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

1
public function handle(Login $event)
2
{
3
    // get logged in user's email and username

4
    $email = $event->user->email;
5
    $username = $event->user->name;
6
    
7
    // send email notification about login

8
}

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

Создание пользовательского события

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

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

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

1
<?php
2
namespace App\Providers;
3
use Illuminate\Support\Facades\Event;
4
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
5
class EventServiceProvider extends ServiceProvider
6
{
7
    /**

8
     * The event listener mappings for the application.

9
     *

10
     * @var array

11
     */
12
    protected $listen = [
13
        'App\Events\ClearCache' => [
14
        'App\Listeners\WarmUpCache',
15
        ],
16
    ];
17
    /**

18
     * Register any events for your application.

19
     *

20
     * @return void

21
     */
22
    public function boot()
23
    {
24
        parent::boot();
25
        //

26
    }
27
}

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

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

1
php artisan event:generate

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

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

1
<?php
2
namespace App\Events;
3
use Illuminate\Broadcasting\Channel;
4
use Illuminate\Queue\SerializesModels;
5
use Illuminate\Broadcasting\PrivateChannel;
6
use Illuminate\Broadcasting\PresenceChannel;
7
use Illuminate\Foundation\Events\Dispatchable;
8
use Illuminate\Broadcasting\InteractsWithSockets;
9
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
10
class ClearCache
11
{
12
    use Dispatchable, InteractsWithSockets, SerializesModels;
13
    
14
    public $cache_keys = [];
15
    /**

16
     * Create a new event instance.

17
     *

18
     * @return void

19
     */
20
    public function __construct(Array $cache_keys)
21
    {
22
        $this->cache_keys = $cache_keys;
23
    }
24
    /**

25
     * Get the channels the event should broadcast on.

26
     *

27
     * @return Channel|array

28
     */
29
    public function broadcastOn()
30
    {
31
        return new PrivateChannel('channel-name');
32
    }
33
}

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

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

1
<?php
2
namespace App\Listeners;
3
use App\Events\ClearCache;
4
use Illuminate\Queue\InteractsWithQueue;
5
use Illuminate\Contracts\Queue\ShouldQueue;
6
class WarmUpCache
7
{
8
    /**

9
     * Create the event listener.

10
     *

11
     * @return void

12
     */
13
    public function __construct()
14
    {
15
        //

16
    }
17
    /**

18
     * Handle the event.

19
     *

20
     * @param  ClearCache  $event

21
     * @return void

22
     */
23
    public function handle(ClearCache $event)
24
    {
25
        if (isset($event->cache_keys) && count($event->cache_keys)) {
26
            foreach ($event->cache_keys as $cache_key) {
27
                // generate cache for this key

28
                // warm_up_cache($cache_key)

29
            }
30
        }
31
    }
32
}

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

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

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

1
<?php
2
namespace App\Http\Controllers;
3
use App\Http\Controllers\Controller;
4
use App\Library\Services\Contracts\CustomServiceInterface;
5
use App\Post;
6
use Illuminate\Support\Facades\Gate;
7
use App\Events\ClearCache;
8
class EventController extends Controller
9
{
10
    public function index()
11
    {
12
        // ...

13
        
14
        // you clear specific caches at this stage

15
        $arr_caches = ['categories', 'products'];
16
        
17
        // want to raise ClearCache event

18
        event(new ClearCache($arr_caches));
19
        
20
        // ...

21
    }
22
}

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

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

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

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

Что такое подписчик событий?

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

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

1
<?php
2
// app/Listeners/ExampleEventSubscriber.php

3
namespace App\Listeners;
4
class ExampleEventSubscriber
5
{
6
    /**

7
     * Handle user login events.

8
     */
9
    public function sendEmailNotification($event) {
10
        // get logged in username

11
        $email = $event->user->email;
12
        $username = $event->user->name;
13
        
14
        // send email notification about login...

15
    }
16
    /**

17
     * Handle user logout events.

18
     */
19
    public function warmUpCache($event) {
20
        if (isset($event->cache_keys) && count($event->cache_keys)) {
21
            foreach ($event->cache_keys as $cache_key) {
22
                // generate cache for this key

23
                // warm_up_cache($cache_key)

24
            }
25
        }
26
    }
27
    /**

28
     * Register the listeners for the subscriber.

29
     *

30
     * @param  Illuminate\Events\Dispatcher  $events

31
     */
32
    public function subscribe($events)
33
    {
34
        $events->listen(
35
            'Illuminate\Auth\Events\Login',
36
            'App\Listeners\ExampleEventSubscriber@sendEmailNotification'
37
        );
38
        
39
        $events->listen(
40
            'App\Events\ClearCache',
41
            'App\Listeners\ExampleEventSubscriber@warmUpCache'
42
        );
43
    }
44
}

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

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

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

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

1
<?php
2
namespace App\Providers;
3
use Illuminate\Support\Facades\Event;
4
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
5
class EventServiceProvider extends ServiceProvider
6
{
7
    /**

8
     * The subscriber classes to register.

9
     *

10
     * @var array

11
     */
12
    protected $subscribe = [
13
        'App\Listeners\ExampleEventSubscriber',
14
    ];
15
    /**

16
     * Register any events for your application.

17
     *

18
     * @return void

19
     */
20
    public function boot()
21
    {
22
        parent::boot();
23
        //

24
    }
25
}

Итак, это был класс подписчиков событий и на этом данная статья заканчивается.

Заключение

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

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

Оставляйте свои комментарии ниже!