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

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

  • 481

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('Ошибка!');
});

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

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

Как работают 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(...);
}

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

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

Решение: 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());

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

Первый месяц за 0 рублей
Хостинг для сайта, который должен работать стабильно
Перенесите проект или запустите новый сайт на Siteko.net и протестируйте сервис без предоплаты.
Перейти к хостингу

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

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

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

Вывод

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

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

Хостинг Siteko

Первый месяц бесплатно

Хостинг Siteko.net для стабильного запуска сайта

Разместите проект на Siteko.net и проверьте скорость, панель управления и поддержку без стартовой оплаты.

  • 1 месяц бесплатно для новых клиентов сразу после выбора тарифа.
  • Быстрый старт для лендинга, блога или корпоративного сайта.
  • Поддержка рядом поможет с переносом и настройкой проекта.
Выбрать тариф