Выносим регистрацию событий в Laravel в отдельные классы

Убираем тонны кода из EventServiceProvider

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

Listen property in EventServiceProvider is too long

Со временем, свойство класса $listen может вырасти до нескольких сотен строк кода. Как можно понять, это будет не так просто читать и поддерживать 😵

Я предлагаю вам сделать классы, которые я называю "регистраторы событий" (event registers). После того, как вы это сделаете, ваш EventServiceProvider будет выглядеть уже по-другому:

Как вы можете видеть, появилось новое свойство - массив $registers, куда вы можете добавлять наши "регистраторы событий".

Лучше ли теперь стало читать и поддерживать код? Конечно лучше! 😎

Шаг 1. Создание папки EventRegisters

Хороший способ - это хранить наши регистраторы в отдельной папке (я такую назвал EventRegisters). Давайте создадим её прямо в папке Providers.

Шаг 2. Создание абстрактного класса

Создайте новый файл AbstractEventRegister.php внутри нашей вновь созданной папки и вставьте туда следующий код:

1 2 3 4 5 6 7 8 9 10 11 12 13
<?php   namespace App\Providers\EventRegisters;   abstract class AbstractEventRegister { protected $listen = [];   public function listens(): array { return $this->listen; } }

Шаг 3. Создание регистраторов событий

Now you can create as many event registration classes as you need. These classes must extends AbstractEventRegister and have the protected $listen property, like in EventServiceProvider.

Теперь вы можете создать столько регистраторов событий, сколько вам необходимо. Эти классы должны быть отнаследованы от AbstractEventRegister и иметь защищенное (protected) свойство $listen, прямо как в нашем EventServiceProvider.

Например, давайте создадим регистратор событий для модели Post:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
<?php   namespace App\Providers\EventRegisters;   use App\Events\Post\PostCreated; use App\Events\Post\PostDeleted; use App\Events\Post\PostUpdated; use App\Listeners\Post\SendPostCreatedNotification; use App\Listeners\Post\SendPostDeletedNotification; use App\Listeners\Post\SendPostUpdatedNotification;   class PostEvents extends AbstractEventRegister { /** * The event listener mappings for the application. * * @var array */ protected $listen = [ PostCreated::class => [ SendPostCreatedNotification::class, ], PostUpdated::class => [ SendPostUpdatedNotification::class, ], PostDeleted::class => [ SendPostDeletedNotification::class, ], ]; }

Шаг 4. Создание трейта для EventServiceProvider

В моем приложении я храню трейты в папке /app/Traits/Providers, но вы можете создать его там, где хотите.

Создайте наш трейт, назвав его EventRegistration.php и вставьте в него следующее содержимое:

1 2 3 4 5 6 7 8 9 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 45 46 47 48
<?php   namespace App\Traits\Providers;   use App\Contracts\Providers\EventRegister; use Event;   trait EventRegistration { /** * Get event registers. * * @return array */ public function registers() { return $this->registers ?? []; }   /** * Register events and listeners. * * @return void */ public function registerEvents() { $eventRegisters = $this->registers();   if (!$eventRegisters) { return; }   foreach ($eventRegisters as $eventRegisterClass) { /** @var EventRegister $eventRegister */ $eventRegister = new $eventRegisterClass();   if (!$events = $eventRegister->listens()) { continue; }   foreach ($events as $event => $listeners) { foreach (array_unique($listeners) as $listener) { Event::listen($event, $listener); } } } } }

Шаг 5. Дайте EventServiceProvider знать о наших регистраторах событий

Подключим наш трейт используя оператор use в начале класса EventServiceProver. После этого, необходимо добавить $this->registerEvents(); в конец метода boot.

После всех этих манипуляций, наш EventServiceProvider будет выглядеть как-то так:

1 2 3 4 5 6 7 8 9 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 45 46 47 48 49
<?php   namespace App\Providers;   use App\Providers\EventRegisters\PostEvents; use App\Traits\Providers\EventRegistration; use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;   class EventServiceProvider extends ServiceProvider { use EventRegistration;   /** * The event listener mappings for the application. * * @var array */ protected $listen = [ Registered::class => [ SendEmailVerificationNotification::class, ], ];   /** * Event registers. * * @var array * @link https://sarvarov.dev/laravel/better-event-registration.html */ protected $registers = [ PostEvents::class,   /* Put here your event registers */ ];   /** * Register any events for your application. * * @return void */ public function boot() { parent::boot();   $this->registerEvents(); } }

Теперь, если нам нужно зарегистрировать какую-то группу событий, мы можем вынести это в отдельный класс-регистратор и подключить его в EventServiceProvider (в защищенном свойстве $registers). Вот и всё!

Комментарии

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: