Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як працюють Markdown-листи і листи в черзі і навіщо листу afterCommit?

Markdown-листи - шаблони з готовими компонентами, які Laravel перетворює на адаптивний HTML з вбудованими стилями й одночасно на текстову версію:

php artisan make:mail OrderShipped --markdown=mail.orders.shipped
<x-mail::message>
# Замовлення відправлено

Ваше замовлення №{{ $order->number }} вже в дорозі.

<x-mail::button :url="$trackingUrl">
Відстежити посилку
</x-mail::button>

<x-mail::table>
| Товар | Кількість |
|:------|----------:|
@foreach ($order->items as $item)
| {{ $item->name }} | {{ $item->quantity }} |
@endforeach
</x-mail::table>

Дякуємо,<br>{{ config('app.name') }}
</x-mail::message>

Компоненти й CSS можна опублікувати (vendor:publish --tag=laravel-mail) і змінити під свій бренд. Головна перевага - не потрібно вручну писати табличну верстку, яку вимагають поштові клієнти.

Листи в черзі. Надсилання через SMTP чи API провайдера займає сотні мілісекунд і може впасти. Користувач не має на це чекати:

Mail::to($user)->queue(new OrderShipped($order));
Mail::to($user)->later(now()->addMinutes(10), new OrderShipped($order));

Або завжди в черзі - інтерфейс ShouldQueue на класі, і тоді навіть send() ставить лист у чергу.

SerializesModels у черзі зберігає лише ідентифікатор моделі, а воркер перечитує модель з бази перед надсиланням.

Навіщо afterCommit:

DB::transaction(function () use ($order) {
    $order->update(['status' => 'shipped']);
    Mail::to($order->customer)->queue(new OrderShipped($order));
    // ... ще операції, які можуть впасти
});

Проблеми без нього:

  • воркер може взяти завдання до коміту транзакції - модель ще не оновлена чи взагалі не існує, і лист міститиме старі дані або завдання впаде з ModelNotFoundException;
  • якщо транзакція відкотилася, лист про «відправлене замовлення» все одно піде.
Mail::to($order->customer)->queue((new OrderShipped($order))->afterCommit());

Тепер лист ставиться в чергу лише після успішного коміту, а при відкаті - не ставиться взагалі. Глобально це вмикає after_commit => true у конфігурації підключення черги.

Обробка збоїв: невдалі листи потрапляють у failed_jobs; можна задати $tries і backoff на класі листа, як у звичайного завдання.

Докладніше в документації: Пошта: листи в черзі й транзакції

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання