Ой, ничего не найдено!

К сожалению, по вашему запросу пока ничего нет (но это только пока!), зато вы можете подписаться на нашу замечательную email-рассылку, чтобы не пропустить самое интересное в будущем.

  • 33

Laravel Observers и ShouldHandleEventsAfterCommit: зачем и как использовать

  • 2 минуты на чтение

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

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

В этой статье я разберу:

  • Что такое транзакции в Laravel
  • Как работают observers
  • Почему важно использовать ShouldHandleEventsAfterCommit
  • Жизненные примеры с багами и их исправлением

Что такое транзакция в Laravel?

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

Пример:

use Illuminate\Support\Facades\DB;

DB::transaction(function () {
    $user = User::create([...]);

    $user->profile()->create([...]);

    // Ошибка, всё откатится
    throw new \Exception('Ошибка!');
});

В этом коде создаётся пользователь и его профиль. Но если происходит ошибка, база данных откатит оба действия. Это удобно и безопасно — если только никакие побочные эффекты не произошли раньше времени.

Специальное предложение: бесплатный хостинг на полгода!
Введите промокод FREE6MONTH при регистрации и наслаждайтесь надежным хостингом бесплатно.

Как работают Observers

Observers — это классы, которые реагируют на события модели: created, updated, deleted и т.д.

Пример:

class UserObserver
{
    public function created(User $user): void
    {
        Mail::to($user->email)->send(new WelcomeMail($user));
    }
}

Такой обработчик автоматически отправит письмо новому пользователю после создания записи в базе.

Проблема: Observer срабатывает до завершения транзакции

Если вы создаёте пользователя внутри DB::transaction(...), Laravel по умолчанию немедленно вызывает created(), даже если транзакция ещё не завершена.

Пример бага:

DB::transaction(function () {
    User::create([ 'email' => 'test@example.com' ]);
    throw new \Exception('Ошибка!');
});

Если в UserObserver прописано:

public function created(User $user): void
{
    Mail::to($user->email)->send(...);
}

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

Бесплатный хостинг на 6 месяцев для новых пользователей!
Примените промокод FREE6MONTH и получите высокоскоростной хостинг без оплаты.

Решение: ShouldHandleEventsAfterCommit

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

use Illuminate\Contracts\Events\ShouldHandleEventsAfterCommit;

class UserObserver implements ShouldHandleEventsAfterCommit
{
    public function created(User $user): void
    {
        // Этот код выполнится только после успешного commit'а
    }
}

Теперь, если транзакция откатится — created() не будет вызван вовсе. Если commit прошёл — вызов произойдёт сразу после него.

Жизненные примеры использования

1. Создание связанных моделей

public function created(User $user): void
{
    $user->profile()->create([...]);
}

Без интерфейса: профиль может быть создан, а пользователь — нет (если транзакция откатится).

С интерфейсом: создаётся только если всё успешно.

2. Аудит и логирование

AuditLog::create([
    'action' => 'created user',
    'user_id' => $user->id,
]);

Без интерфейса: в логе будет запись о пользователе, которого нет.

3. Уведомления и письма

Notification::send($user, new WelcomeNotification());

Без интерфейса: уведомление отправится, даже если пользователь не сохранён.

Бесплатный хостинг на 6 месяцев для новых пользователей!
Примените промокод FREE6MONTH и получите высокоскоростной хостинг без оплаты.

Когда стоит использовать ShouldHandleEventsAfterCommit?

Рекомендуется использовать его, если в обработчике:

  • Отправляются письма или уведомления
  • Создаются связанные модели
  • Пишется лог/аудит
  • Обновляются внешние API, кеши, очереди

Вывод

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

Если вы ещё не используете этот интерфейс — самое время внедрить его в те Observer'ы, где есть внешние действия.

Хостинг, на который можно положиться!
Siteko.net

Устали от медленного хостинга или дорогих тарифов? Тогда вам к нам! Siteko.net — это быстрый и простой хостинг для тех, кто ценит удобство и стабильность.

  • Без падений и нервов — наш uptime почти всегда 100%.
  • Гибкие тарифы — только нужные функции, ничего лишнего.
  • Скорость— сайты грузятся, как пуля!
  • Удобно — разобраться сможет даже новичок, всё под рукой.
  • Поддержка всегда рядом 24/7 поможем решить любой вопрос.

Заходите на Siteko.net и попробуйте нас бесплатно первый месяц! Мы делаем всё, чтобы ваш сайт работал без проблем.

Siteko.net — просто, быстро и надёжно!