Вступление
События Laravel предоставляют простую реализацию наблюдателя, позволяющую вам подписываться и прослушивать различные события, которые происходят в вашем приложении. Классы событий обычно хранятся в каталоге, а их слушатели - в . Не беспокойтесь, если вы не увидите эти каталоги в своем приложении, поскольку они будут созданы для вас, когда вы генерируете события и прослушиватели с помощью консольных команд Artisan.app/Events
app/Listeners
События служат отличным способом разъединить различные аспекты вашего приложения, поскольку одно событие может иметь несколько слушателей, которые не зависят друг от друга. Например, вы можете отправлять уведомления Slack своему пользователю каждый раз, когда заказ отправлен. Вместо того, чтобы связывать код обработки заказа с кодом уведомления Slack, вы можете вызвать OrderShipped
событие, которое слушатель может получить и преобразовать в уведомление Slack.
Регистрация событий и слушателей
EventServiceProvider
В комплекте с приложением Laravel обеспечивает удобное место для регистрации всех слушателей событий вашего приложения. listen
Свойство содержит массив всех событий (ключи) и их слушателей (значения). Вы можете добавить столько событий в этот массив, сколько требует ваше приложение. Например, давайте добавим OrderShipped
событие:
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'App\Events\OrderShipped' => [
'App\Listeners\SendShipmentNotification',
],
];
Генерация событий и слушателей
Конечно, создание файлов для каждого события и слушателя вручную затруднительно. Вместо этого добавьте слушателей и события к себе EventServiceProvider
и используйте команду. Эта команда будет генерировать любые события или прослушиватели, которые перечислены в вашем . События и слушатели, которые уже существуют, останутся нетронутыми:event:generate
EventServiceProvider
php artisan event:generate
Регистрация событий вручную
Как правило, события должны быть зарегистрированы через EventServiceProvider
$listen
массив; однако вы также можете зарегистрировать события, основанные на замыкании, вручную, используя boot
метод EventServiceProvider
:
/**
* Register any other events for your application.
*
* @return void
*/
public function boot()
{
parent::boot();
Event::listen('event.name', function ($foo, $bar) {
//
});
}
Слушатели событий с подстановочными знаками
Вы даже можете зарегистрировать слушателей, используя *
параметр подстановки, позволяющий перехватывать несколько событий на одном и том же слушателе. Слушатели подстановочных знаков получают имя события в качестве первого аргумента и весь массив данных события в качестве второго аргумента:
Event::listen('event.*', function ($eventName, array $data) {
//
});
Обнаружение событий
Обнаружение событий доступно для Laravel 5.8.9 или новее.
Вместо регистрации событий и прослушивателей вручную в $listen
массиве EventServiceProvider
, вы можете включить автоматическое обнаружение событий. Когда обнаружение событий включено, Laravel автоматически найдет и зарегистрирует ваши события и слушателей, отсканировав Listeners
каталог вашего приложения . Кроме того, любые явно определенные события, перечисленные в, EventServiceProvider
все равно будут зарегистрированы.
Laravel находит прослушиватели событий путем сканирования классов слушателей с использованием отражения. Когда Laravel находит какой-либо метод класса слушателя, который начинается с handle
, Laravel зарегистрирует эти методы в качестве слушателей события для события, на которое указывается тип в сигнатуре метода:
use App\Events\PodcastProcessed;
class SendPodcastProcessedNotification
{
/**
* Handle the given event.
*
* @param \App\Events\PodcastProcessed
* @return void
*/
public function handle(PodcastProcessed $event)
{
//
}
}
По умолчанию обнаружение событий отключено, но вы можете включить его, переопределив shouldDiscoverEvents
метод вашего приложения EventServiceProvider
:
/**
* Determine if events and listeners should be automatically discovered.
*
* @return bool
*/
public function shouldDiscoverEvents()
{
return true;
}
По умолчанию все прослушиватели в каталоге Listeners вашего приложения будут сканироваться. Если вы хотите определить дополнительные каталоги для сканирования, вы можете переопределить discoverEventsWithin
метод в вашем EventServiceProvider
:
/**
* Get the listener directories that should be used to discover events.
*
* @return array
*/
protected function discoverEventsWithin()
{
return [
$this->app->path('Listeners'),
];
}
В производственной среде вы, вероятно, не хотите, чтобы инфраструктура сканировала всех ваших слушателей при каждом запросе. Поэтому в процессе развертывания вы должны выполнить команду Artisan, чтобы кэшировать манифест всех событий и прослушивателей вашего приложения. Этот манифест будет использоваться платформой для ускорения процесса регистрации событий. Команда может быть использована для уничтожения кэша.event:cache
event:clear
Команда может быть использована для отображения списка всех событий и слушателей , зарегистрированных приложением.
event:list
Определение событий
Класс события - это контейнер данных, который содержит информацию, связанную с событием. Например, предположим, что наше сгенерированное OrderShipped
событие получает объект Eloquent ORM :
<?php
namespace App\Events;
use App\Order;
use Illuminate\Queue\SerializesModels;
class OrderShipped
{
use SerializesModels;
public $order;
/**
* Create a new event instance.
*
* @param \App\Order $order
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
}
Как видите, этот класс событий не содержит логики. Это контейнер для Order
экземпляра, который был куплен. SerializesModels
Черта используется событие будет корректно сериализовать любые красноречивые модели , если объект события сериализации с помощью РНР serialize
функции.
Определение слушателей
Далее, давайте посмотрим на слушателя нашего примера события. Слушатели событий получают экземпляр события в своем handle
методе. Команда автоматически импортирует соответствующий класс событий и напечатает подсказку о событии в методе. В рамках метода вы можете выполнить любые действия, необходимые для ответа на событие:event:generate
handle
handle
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
class SendShipmentNotification
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param \App\Events\OrderShipped $event
* @return void
*/
public function handle(OrderShipped $event)
{
// Access the order using $event->order...
}
}
Ваши слушатели событий могут также указывать любые зависимости, которые им нужны от их конструкторов. Все прослушиватели событий разрешаются через служебный контейнер Laravel , поэтому зависимости будут вставлены автоматически.
Остановка распространения события
Иногда вы можете остановить распространение события на других слушателей. Вы можете сделать это, вернувшись false
из handle
метода вашего слушателя .
Прослушиватели событий в очереди
Слушатели в очереди могут быть полезны, если ваш слушатель будет выполнять медленную задачу, такую как отправка электронной почты или отправка HTTP-запроса. Прежде чем начать работу с прослушивателями в очереди, обязательно настройте свою очередь и запустите прослушиватель очереди на своем сервере или в локальной среде разработки.
Чтобы указать, что слушатель должен быть поставлен в очередь, добавьте ShouldQueue
интерфейс в класс слушателя. Слушатели, сгенерированные командой Artisan, уже импортировали этот интерфейс в текущее пространство имен, поэтому вы можете использовать его немедленно:event:generate
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
//
}
Это оно! Теперь, когда этот прослушиватель вызывается для события, он автоматически будет поставлен в очередь диспетчером событий с использованием системы очередей Laravel . Если никакие исключения не генерируются, когда слушатель выполняется в очереди, заданное в очереди задание будет автоматически удалено после завершения обработки.
Настройка подключения к очереди и имени очереди
Если вы хотите , чтобы настроить подключение очереди, имя очереди, или в очереди время задержки прослушивателя событий, вы можете определить $connection
, $queue
или $delay
свойства на классе слушателя:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
/**
* The name of the connection the job should be sent to.
*
* @var string|null
*/
public $connection = 'sqs';
/**
* The name of the queue the job should be sent to.
*
* @var string|null
*/
public $queue = 'listeners';
/**
* The time (seconds) before the job should be processed.
*
* @var int
*/
public $delay = 60;
}
Доступ к очереди вручную
Если вам нужно вручную получить доступ к заданию delete
и release
методам очереди слушателя , вы можете сделать это, используя эту черту. Эта черта импортируется по умолчанию для сгенерированных слушателей и предоставляет доступ к этим методам:Illuminate\Queue\InteractsWithQueue
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
/**
* Handle the event.
*
* @param \App\Events\OrderShipped $event
* @return void
*/
public function handle(OrderShipped $event)
{
if (true) {
$this->release(30);
}
}
}
Обработка неудачных заданий
Иногда ваши слушатели событий в очереди могут потерпеть неудачу. Если прослушиватель в очереди превышает максимальное количество попыток, как определено вашим работником очереди, failed
метод будет вызван на вашем слушателе. failed
Метод получает экземпляр события и исключение , которое вызвало отказ:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
/**
* Handle the event.
*
* @param \App\Events\OrderShipped $event
* @return void
*/
public function handle(OrderShipped $event)
{
//
}
/**
* Handle a job failure.
*
* @param \App\Events\OrderShipped $event
* @param \Exception $exception
* @return void
*/
public function failed(OrderShipped $event, $exception)
{
//
}
}
Диспетчерские события
Для отправки события вы можете передать экземпляр события event
помощнику. Помощник отправит событие всем зарегистрированным слушателям. Поскольку event
помощник доступен по всему миру, вы можете вызывать его из любого места в вашем приложении:
<?php
namespace App\Http\Controllers;
use App\Order;
use App\Events\OrderShipped;
use App\Http\Controllers\Controller;
class OrderController extends Controller
{
/**
* Ship the given order.
*
* @param int $orderId
* @return Response
*/
public function ship($orderId)
{
$order = Order::findOrFail($orderId);
// Order shipment logic...
event(new OrderShipped($order));
}
}
При тестировании может быть полезно утверждать, что определенные события были отправлены без фактического запуска их слушателей. Встроенные в Laravel помощники по тестированию делают это проще простого.
Подписчики событий
Написание событий подписчиков
Подписчики событий - это классы, которые могут подписываться на несколько событий внутри самого класса, что позволяет вам определять несколько обработчиков событий в одном классе. Подписчики должны определить subscribe
метод, которому будет передан экземпляр диспетчера событий. Вы можете вызвать listen
метод данного диспетчера для регистрации прослушивателей событий:
<?php
namespace App\Listeners;
class UserEventSubscriber
{
/**
* Handle user login events.
*/
public function handleUserLogin($event) {}
/**
* Handle user logout events.
*/
public function handleUserLogout($event) {}
/**
* Register the listeners for the subscriber.
*
* @param \Illuminate\Events\Dispatcher $events
*/
public function subscribe($events)
{
$events->listen(
'Illuminate\Auth\Events\Login',
'App\Listeners\UserEventSubscriber@handleUserLogin'
);
$events->listen(
'Illuminate\Auth\Events\Logout',
'App\Listeners\UserEventSubscriber@handleUserLogout'
);
}
}
Регистрация подписчиков на события
После написания подписчика вы готовы зарегистрировать его у диспетчера событий. Вы можете зарегистрировать подписчиков, используя $subscribe
собственность на EventServiceProvider
. Например, давайте добавим UserEventSubscriber
в список:
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
//
];
/**
* The subscriber classes to register.
*
* @var array
*/
protected $subscribe = [
'App\Listeners\UserEventSubscriber',
];
}
0 комментариев