Події (Events)

Introduction

Події Laravel надають просту реалізацію шаблону спостерігача, дозволяючи підписуватися та слухати різні події, що відбуваються у вашому застосунку. Класи подій зазвичай зберігаються в директорії app/Events, тоді як їхні слухачі зберігаються в app/Listeners. Не хвилюйтеся, якщо ви не бачите цих директорій у вашому застосунку, оскільки вони будуть створені для вас, коли ви генеруватимете події та слухачів за допомогою Artisan консольних команд.

Події служать чудовим способом роз'єднання різних аспектів вашого застосунку, оскільки одна подія може мати декілька слухачів, які не залежать один від одного. Наприклад, ви можете захотіти надіслати сповіщення в Slack вашому користувачу щоразу, коли замовлення відправлено. Замість того, щоб зв'язувати ваш код обробки замовлень з кодом сповіщення в Slack, ви можете викликати подію App\Events\OrderShipped, яку слухач може отримати і використати для відправки сповіщення в Slack.

Генерація Подій та Слухачів

Щоб швидко згенерувати події та слухачі, ви можете використовувати команди Artisan make:event та make:listener:

php artisan make:event PodcastProcessed
 
php artisan make:listener SendPodcastNotification --event=PodcastProcessed

Для зручності, ви також можете викликати команди Artisan make:event та make:listener без додаткових аргументів. Коли ви це робите, Laravel автоматично запитає вас про ім'я класу, а при створенні слухача - про подію, яку він повинен слухати:

php artisan make:event
 
php artisan make:listener

Реєстрація Подій та Слухачів

Виявлення подій

За замовчуванням Laravel автоматично знайде та зареєструє ваші слухачі подій, скануючи директорію Listeners вашого застосунку. Коли Laravel знаходить будь-який метод класу слухача, що починається з handle або __invoke, Laravel зареєструє ці методи як слухачі подій для події, яка вказана в сигнатурі методу:

use App\Events\PodcastProcessed;
 
class SendPodcastNotification
{
/**
* Обробити подію.
*/
public function handle(PodcastProcessed $event): void
{
// ...
}
}

Ви можете слухати кілька подій, використовуючи об'єднані типи PHP:

/**
 * Handle the event.
 */
public function handle(PodcastProcessed|PodcastPublished $event): void
{
    // ...
}

Якщо ви плануєте зберігати ваші слухачі в іншій директорії або в декількох директоріях, ви можете вказати Laravel сканувати ці директорії, використовуючи метод withEvents у файлі bootstrap/app.php вашого застосунку:

->withEvents(discover: [
    __DIR__.'/../app/Domain/Orders/Listeners',
])

Ви можете сканувати слухачів у декількох подібних каталогах, використовуючи символ * як підстановочний знак:

->withEvents(discover: [
    __DIR__.'/../app/Domain/*/Listeners',
])

Команда event:list може бути використана для переліку всіх слухачів, зареєстрованих у вашому застосунку:

php artisan event:list

Виявлення подій у продакшені

Щоб прискорити ваш застосунок, ви повинні кешувати маніфест усіх слухачів вашого застосунку, використовуючи команди Artisan optimize або event:cache. Зазвичай, цю команду слід виконувати як частину процесу розгортання вашого застосунку. Цей маніфест буде використовуватися фреймворком для прискорення процесу реєстрації подій. Команда event:clear може бути використана для знищення кешу подій.

Ручна Реєстрація Подій

Використовуючи фасад Event, ви можете вручну реєструвати події та їх відповідні слухачі в методі boot вашого застосунку AppServiceProvider:

use App\Domain\Orders\Events\PodcastProcessed;
use App\Domain\Orders\Listeners\SendPodcastNotification;
use Illuminate\Support\Facades\Event;
 
/**
* Ініціалізувати будь-які сервіси застосунку.
*/
public function boot(): void
{
Event::listen(
PodcastProcessed::class,
SendPodcastNotification::class,
);
}

Команда event:list може бути використана для переліку всіх слухачів, зареєстрованих у вашому застосунку:

php artisan event:list

Слухачі на основі замикань

Зазвичай слухачі визначаються як класи; однак ви також можете вручну зареєструвати слухачі подій на основі замикань у методі boot вашого застосунку AppServiceProvider:

use App\Events\PodcastProcessed;
use Illuminate\Support\Facades\Event;
 
/**
* Ініціалізувати будь-які сервіси застосунку.
*/
public function boot(): void
{
Event::listen(function (PodcastProcessed $event) {
// ...
});
}

Черга анонімних слухачів подій

Коли ви реєструєте слухачів подій на основі замикань, ви можете обгорнути замикання слухача у функцію Illuminate\Events\queueable, щоб вказати Laravel виконати слухача за допомогою черги:

use App\Events\PodcastProcessed;
use function Illuminate\Events\queueable;
use Illuminate\Support\Facades\Event;
 
/**
* Ініціалізувати будь-які сервіси застосунку.
*/
public function boot(): void
{
Event::listen(queueable(function (PodcastProcessed $event) {
// ...
}));
}

Як і у випадку з поставленими в чергу завданнями, ви можете використовувати методи onConnection, onQueue та delay для налаштування виконання поставленого в чергу слухача:

Event::listen(queueable(function (PodcastProcessed $event) {
    // ...
})->onConnection('redis')->onQueue('podcasts')->delay(now()->addSeconds(10)));

Якщо ви хочете обробляти збої анонімних слухачів у черзі, ви можете надати замикання методу catch під час визначення слухача queueable. Це замикання отримає екземпляр події та екземпляр Throwable, який спричинив збій слухача:

use App\Events\PodcastProcessed;
use function Illuminate\Events\queueable;
use Illuminate\Support\Facades\Event;
use Throwable;
 
Event::listen(queueable(function (PodcastProcessed $event) {
// ...
})->catch(function (PodcastProcessed $event, Throwable $e) {
// Слухач черги завершився з помилкою...
}));

Анонімні слухачі групи подій

Ви також можете зареєструвати слухачів, використовуючи символ * як параметр-замінник, що дозволяє обробляти декілька подій одним слухачем. Слухачі з замінниками отримують назву події як свій перший аргумент і весь масив даних події як свій другий аргумент:

Event::listen('event.*', function (string $eventName, array $data) {
    // ...
});

Визначення Подій

Клас події по суті є контейнером даних, який містить інформацію, пов'язану з подією. Наприклад, припустимо, подія App\Events\OrderShipped отримує об'єкт Eloquent ORM:

<?php
 
namespace App\Events;
 
use App\Models\Order;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
 
class OrderShipped
{
use Dispatchable, InteractsWithSockets, SerializesModels;
 
/**
* Створити новий екземпляр події.
*/
public function __construct(
public Order $order,
) {}
}

Як ви можете бачити, цей клас події не містить логіки. Це контейнер для екземпляра App\Models\Order, який був придбаний. Трейт SerializesModels, що використовується подією, буде коректно серіалізувати будь-які моделі Eloquent, якщо об'єкт події серіалізується за допомогою PHP-функції serialize, наприклад, при використанні чергових слухачів.

Визначення Слухачів

Далі, давайте розглянемо слухач для нашої події-прикладу. Слухачі подій отримують екземпляри подій у своєму методі handle. Команда Artisan make:listener, коли викликається з опцією --event, автоматично імпортує відповідний клас події та вказує тип події в методі handle. У межах методу handle ви можете виконувати будь-які дії, необхідні для реагування на подію:

<?php
 
namespace App\Listeners;
 
use App\Events\OrderShipped;
 
class SendShipmentNotification
{
/**
* Створити слухача події.
*/
public function __construct() {}
 
/**
* Обробити подію.
*/
public function handle(OrderShipped $event): void
{
// Отримати доступ до замовлення через $event->order...
}
}

Ваші слухачі подій також можуть вказувати будь-які залежності, які їм потрібні, у своїх конструкторах. Усі слухачі подій вирішуються через Сервіс-контейнер Laravel, тому залежності будуть впроваджені автоматично.

Зупинка Поширення Події

Іноді ви можете захотіти зупинити поширення події до інших слухачів. Ви можете зробити це, повернувши false з методу handle вашого слухача.

Черга обробників подій

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

Щоб вказати, що слухач повинен бути поставлений у чергу, додайте інтерфейс ShouldQueue до класу слухача. Слухачі, згенеровані командами Artisan make:listener, вже мають цей інтерфейс імпортованим у поточний простір імен, тому ви можете використовувати його негайно:

<?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
{
    /**
     * Ім'я з'єднання, до якого має бути відправлено завдання.
     *
     * @var string|null
     */
    public $connection = 'sqs';
 
    /**
     * Назва черги, до якої слід відправити завдання.
     *
     * @var string|null
     */
    public $queue = 'listeners';
 
    /**
     * Час (у секундах) до обробки завдання.
     *
     * @var int
     */
    public $delay = 60;
}

Якщо ви хочете визначити з'єднання черги, ім'я черги або затримку слухача під час виконання, ви можете визначити методи viaConnection, viaQueue або withDelay на слухачі:

/**
 * Отримати ім'я з'єднання черги слухача.
 */
public function viaConnection(): string
{
    return 'sqs';
}
 
/**
 * Отримати назву черги слухача.
 */
public function viaQueue(): string
{
    return 'listeners';
}
 
/**
 * Отримати кількість секунд до того, як завдання має бути оброблено.
 */
public function withDelay(OrderShipped $event): int
{
    return $event->highPriority ? 0 : 60;
}

Умовна Постановка Слухачів у Чергу

Іноді вам може знадобитися визначити, чи слід поставити слухача в чергу, на основі деяких даних, які доступні лише під час виконання. Для цього до слухача можна додати метод shouldQueue, щоб визначити, чи слід поставити слухача в чергу. Якщо метод shouldQueue повертає false, слухач не буде поставлений в чергу:

<?php
 
namespace App\Listeners;
 
use App\Events\OrderCreated;
use Illuminate\Contracts\Queue\ShouldQueue;
 
class RewardGiftCard implements ShouldQueue
{
/**
* Нагородити клієнта подарунковою карткою.
*/
public function handle(OrderCreated $event): void
{
// ...
}
 
/**
* Визначити, чи слід ставити слухача в чергу.
*/
public function shouldQueue(OrderCreated $event): bool
{
return $event->order->subtotal >= 5000;
}
}

Ручна взаємодія з чергою

Якщо вам потрібно вручну отримати доступ до методів delete та release базової черги завдань слухача, ви можете зробити це за допомогою трейту Illuminate\Queue\InteractsWithQueue. Цей трейт імпортується за замовчуванням у згенерованих слухачах і надає доступ до цих методів:

<?php
 
namespace App\Listeners;
 
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
 
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
 
/**
* Обробити подію.
*/
public function handle(OrderShipped $event): void
{
if (true) {
$this->release(30);
}
}
}

Черга Слухачів Подій і Транзакції Бази Даних

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

Якщо параметр конфігурації after_commit вашого з'єднання черги встановлено на false, ви все ще можете вказати, що певний слухач у черзі повинен бути відправлений після того, як всі відкриті транзакції бази даних будуть зафіксовані, реалізувавши інтерфейс ShouldQueueAfterCommit у класі слухача:

<?php
 
namespace App\Listeners;
 
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;
use Illuminate\Queue\InteractsWithQueue;
 
class SendShipmentNotification implements ShouldQueueAfterCommit
{
    use InteractsWithQueue;
}

Щоб дізнатися більше про вирішення цих проблем, будь ласка, перегляньте документацію щодо чергових завдань і транзакцій бази даних.

Обробка Невдалих Завдань

Іноді ваші слухачі подій у черзі можуть зазнати невдачі. Якщо слухач у черзі перевищує максимальну кількість спроб, визначену вашим працівником черги, метод failed буде викликано на вашому слухачі. Метод failed отримує екземпляр події та Throwable, що спричинив невдачу:

<?php
 
namespace App\Listeners;
 
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Throwable;
 
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
 
/**
* Обробити подію.
*/
public function handle(OrderShipped $event): void
{
// ...
}
 
/**
* Обробити збій завдання.
*/
public function failed(OrderShipped $event, Throwable $exception): void
{
// ...
}
}

Вказівка максимальної кількості спроб для слухача в черзі

Якщо один із ваших слухачів у черзі стикається з помилкою, ви, ймовірно, не хочете, щоб він продовжував спроби безкінечно. Тому Laravel надає різні способи вказати, скільки разів або як довго можна намагатися виконати слухача.

Ви можете визначити властивість $tries у вашому класі слухача, щоб вказати, скільки разів слухач може бути спробуваний, перш ніж вважатиметься, що він зазнав невдачі:

<?php
 
namespace App\Listeners;
 
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
 
class SendShipmentNotification implements ShouldQueue
{
    use InteractsWithQueue;
 
    /**
     * Кількість спроб виконання слухача в черзі.
     *
     * @var int
     */
    public $tries = 5;
}

Як альтернативу визначенню, скільки разів слухач може бути спробуваний перед тим, як він зазнає невдачі, ви можете визначити час, після якого слухач більше не повинен бути спробуваний. Це дозволяє спробувати слухача будь-яку кількість разів у заданому часовому проміжку. Щоб визначити час, після якого слухач більше не повинен бути спробуваний, додайте метод retryUntil до вашого класу слухача. Цей метод повинен повертати екземпляр DateTime:

use DateTime;
 
/**
 * Визначте час, коли слухач повинен завершити очікування.
 */
public function retryUntil(): DateTime
{
    return now()->addMinutes(5);
}

Якщо визначені обидва retryUntil і tries, Laravel надає перевагу методу retryUntil.

Вказання Відступу для Черги Слухача

Якщо ви хочете налаштувати, скільки секунд Laravel повинен чекати перед повторною спробою виконання слухача, який зіткнувся з винятком, ви можете зробити це, визначивши властивість backoff у вашому класі слухача:

/**
 * Кількість секунд очікування перед повторною спробою чергового слухача.
 *
 * @var int
 */
public $backoff = 3;

Якщо вам потрібна більш складна логіка для визначення часу відкладення слухача, ви можете визначити метод backoff у вашому класі слухача:

/**
 * Обчисліть кількість секунд, яку потрібно зачекати перед повторною спробою чергового слухача.
 */
public function backoff(): int
{
    return 3;
}

Ви можете легко налаштувати "експоненційні" затримки, повертаючи масив значень затримки з методу backoff. У цьому прикладі затримка повторної спроби буде 1 секунда для першої спроби, 5 секунд для другої спроби, 10 секунд для третьої спроби, і 10 секунд для кожної наступної спроби, якщо залишаються ще спроби:

/**
 * Обчисліть кількість секунд, яку потрібно зачекати перед повторною спробою чергового слухача.
 *
 * @return list<int>
 */
public function backoff(): array
{
    return [1, 5, 10];
}

Відправка подій

Щоб відправити подію, ви можете викликати статичний метод dispatch на події. Цей метод доступний на події завдяки трейту Illuminate\Foundation\Events\Dispatchable. Будь-які аргументи, передані методу dispatch, будуть передані конструктору події:

<?php
 
namespace App\Http\Controllers;
 
use App\Events\OrderShipped;
use App\Models\Order;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
 
class OrderShipmentController extends Controller
{
    /**
     * Відправити дане замовлення.
     */
    public function store(Request $request): RedirectResponse
    {
        $order = Order::findOrFail($request->order_id);
 
        // Логіка відправлення замовлення...
 
        OrderShipped::dispatch($order);
 
        return redirect('/orders');
    }
}

Якщо ви хочете умовно відправити подію, ви можете використовувати методи dispatchIf та dispatchUnless:

OrderShipped::dispatchIf($condition, $order);
 
OrderShipped::dispatchUnless($condition, $order);

Під час тестування може бути корисно перевірити, що певні події були відправлені, не викликаючи їхніх слухачів. Вбудовані допоміжні засоби тестування Laravel роблять це дуже просто.

Відправка подій після транзакцій бази даних

Іноді ви можете захотіти вказати Laravel відправляти подію лише після того, як активна транзакція бази даних буде зафіксована. Для цього ви можете реалізувати інтерфейс ShouldDispatchAfterCommit у класі події.

Цей інтерфейс інструктує Laravel не відправляти подію, поки поточна транзакція бази даних не буде зафіксована. Якщо транзакція не вдасться, подія буде відхилена. Якщо жодна транзакція бази даних не виконується, коли подія відправляється, подія буде відправлена негайно:

<?php
 
namespace App\Events;
 
use App\Models\Order;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
 
class OrderShipped implements ShouldDispatchAfterCommit
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
 
    /**
     * Створити новий екземпляр події.
     */
    public function __construct(
        public Order $order,
    ) {}
}

Підписники подій

Написання Підписників Подій

Підписники подій - це класи, які можуть підписуватися на декілька подій безпосередньо в класі підписника, що дозволяє визначати декілька обробників подій в одному класі. Підписники повинні визначити метод subscribe, який отримує екземпляр диспетчера подій. Ви можете викликати метод listen на наданому диспетчері, щоб зареєструвати слухачів подій:

<?php
 
namespace App\Listeners;
 
use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Events\Dispatcher;
 
class UserEventSubscriber
{
    /**
     * Обробка подій входу користувача.
     */
    public function handleUserLogin(Login $event): void {}
 
    /**
     * Обробка подій виходу користувача.
     */
    public function handleUserLogout(Logout $event): void {}
 
    /**
     * Зареєструйте слухачів для підписника.
     */
    public function subscribe(Dispatcher $events): void
    {
        $events->listen(
            Login::class,
            [UserEventSubscriber::class, 'handleUserLogin']
        );
 
        $events->listen(
            Logout::class,
            [UserEventSubscriber::class, 'handleUserLogout']
        );
    }
}

Якщо ваші методи слухача подій визначені безпосередньо в підписнику, вам може бути зручніше повернути масив подій та імен методів з методу subscribe підписника. Laravel автоматично визначить ім'я класу підписника при реєстрації слухачів подій:

<?php
 
namespace App\Listeners;
 
use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Events\Dispatcher;
 
class UserEventSubscriber
{
    /**
     * Обробка подій входу користувача.
     */
    public function handleUserLogin(Login $event): void {}
 
    /**
     * Обробка подій виходу користувача.
     */
    public function handleUserLogout(Logout $event): void {}
 
    /**
     * Зареєструйте слухачів для підписника.
     *
     * @return array<string, string>
     */
    public function subscribe(Dispatcher $events): array
    {
        return [
            Login::class => 'handleUserLogin',
            Logout::class => 'handleUserLogout',
        ];
    }
}

Реєстрація підписників подій

Після написання підписника, Laravel автоматично зареєструє методи обробника в межах підписника, якщо вони відповідають конвенціям виявлення подій Laravel. В іншому випадку, ви можете вручну зареєструвати свого підписника, використовуючи метод subscribe фасаду Event. Зазвичай це слід робити в межах методу boot вашого AppServiceProvider застосунку:

<?php
 
namespace App\Providers;
 
use App\Listeners\UserEventSubscriber;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;
 
class AppServiceProvider extends ServiceProvider
{
/**
* Ініціалізувати будь-які сервіси застосунку.
*/
public function boot(): void
{
Event::subscribe(UserEventSubscriber::class);
}
}

Тестування

Коли тестуєте код, який відправляє події, ви можете захотіти вказати Laravel не виконувати слухачі події, оскільки код слухача може бути протестований безпосередньо і окремо від коду, який відправляє відповідну подію. Звісно, щоб протестувати сам слухач, ви можете створити екземпляр слухача і викликати метод handle безпосередньо у вашому тесті.

Використовуючи метод fake фасаду Event, ви можете запобігти виконанню слухачів, виконати код, що тестується, а потім перевірити, які події були відправлені вашим застосунком, використовуючи методи assertDispatched, assertNotDispatched та assertNothingDispatched:

<?php
 
use App\Events\OrderFailedToShip;
use App\Events\OrderShipped;
use Illuminate\Support\Facades\Event;
 
test('замовлення можна відправити', function () {
Event::fake();
 
// Виконати відправлення замовлення...
 
// Перевірити, що подію було надіслано...
Event::assertDispatched(OrderShipped::class);
 
// Перевірити, що подію було надіслано двічі...
Event::assertDispatched(OrderShipped::class, 2);
 
// Перевірити, що подію не було надіслано...
Event::assertNotDispatched(OrderFailedToShip::class);
 
// Перевірити, що жодної події не було надіслано...
Event::assertNothingDispatched();
});
<?php
 
namespace Tests\Feature;
 
use App\Events\OrderFailedToShip;
use App\Events\OrderShipped;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
 
class ExampleTest extends TestCase
{
/**
* Тестування відправлення замовлення.
*/
public function test_orders_can_be_shipped(): void
{
Event::fake();
 
// Виконати відправлення замовлення...
 
// Перевірити, що подію було надіслано...
Event::assertDispatched(OrderShipped::class);
 
// Перевірити, що подію було надіслано двічі...
Event::assertDispatched(OrderShipped::class, 2);
 
// Перевірити, що подію не було надіслано...
Event::assertNotDispatched(OrderFailedToShip::class);
 
// Перевірити, що жодної події не було надіслано...
Event::assertNothingDispatched();
}
}

Ви можете передати замикання методам assertDispatched або assertNotDispatched, щоб перевірити, що подія була відправлена, яка проходить заданий "тест на істинність". Якщо хоча б одна подія була відправлена, яка проходить заданий тест на істинність, тоді перевірка буде успішною:

Event::assertDispatched(function (OrderShipped $event) use ($order) {
    return $event->order->id === $order->id;
});

Якщо ви просто хочете перевірити, що слухач подій слухає певну подію, ви можете використовувати метод assertListening:

Event::assertListening(
    OrderShipped::class,
    SendShipmentNotification::class
);

Після виклику Event::fake() жодні слухачі подій не будуть виконані. Тому, якщо ваші тести використовують фабрики моделей, які залежать від подій, наприклад, створення UUID під час події creating моделі, ви повинні викликати Event::fake() після використання ваших фабрик.

Імітація підмножини подій

Якщо ви хочете підробити слухачів подій лише для конкретного набору подій, ви можете передати їх у методи fake або fakeFor:

test('orders can be processed', function () {
Event::fake([
OrderCreated::class,
]);
 
$order = Order::factory()->create();
 
Event::assertDispatched(OrderCreated::class);
 
// Інші події надсилаються як зазвичай...
$order->update([
// ...
]);
});
/**
* Тестування процесу замовлення.
*/
public function test_orders_can_be_processed(): void
{
Event::fake([
OrderCreated::class,
]);
 
$order = Order::factory()->create();
 
Event::assertDispatched(OrderCreated::class);
 
// Інші події надсилаються як зазвичай...
$order->update([
// ...
]);
}

Ви можете підробити всі події, за винятком набору вказаних подій, використовуючи метод except:

Event::fake()->except([
    OrderCreated::class,
]);

Фейкові події з обмеженою областю

Якщо ви хочете підробити слухачів подій лише для частини вашого тесту, ви можете використовувати метод fakeFor:

<?php
 
use App\Events\OrderCreated;
use App\Models\Order;
use Illuminate\Support\Facades\Event;
 
test('orders can be processed', function () {
$order = Event::fakeFor(function () {
$order = Order::factory()->create();
 
Event::assertDispatched(OrderCreated::class);
 
return $order;
});
 
// Події надсилаються як зазвичай, і спостерігачі будуть запущені...
$order->update([
// ...
]);
});
<?php
 
namespace Tests\Feature;
 
use App\Events\OrderCreated;
use App\Models\Order;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
 
class ExampleTest extends TestCase
{
/**
* Тестування процесу замовлення.
*/
public function test_orders_can_be_processed(): void
{
$order = Event::fakeFor(function () {
$order = Order::factory()->create();
 
Event::assertDispatched(OrderCreated::class);
 
return $order;
});
 
// Події надсилаються як зазвичай, і спостерігачі будуть запущені...
$order->update([
// ...
]);
}
}