Долгое время отправка писем в Laravel была не очень удобной в сравнении с относительно простым API большинства других функций Laravel. Вот пример отправки письма из документации Laravel 5.2:
Mail::send('emails.reminder', ['user' => $user], function ($m) use ($user) {
$m->from('hello@app.com', 'Ваше приложение');
$m->to($user->email, $user->name)->subject('Ваше напоминание!');
});
Я не говорю, что она ужасна, она намного проще своих конкурентов, но зачастую трудно понять, что происходит в замыкании, а что не происходит, в каком порядке идут параметры и т.д.
Знакомство с Mailables
Mailables — PHP-классы в Laravel 5.3, каждый из которых отвечает за одно письмо: «NewUserWelcome» (приветствие нового пользователя) или «PaymentReceipt» (квитанция об оплате). Появился простой синтаксис «отправки», похожий на управление событиями и задачами, в который вы будете передавать экземпляр нужного вам класса, в данном случае это письмо.
Итак, теперь та же самая отправка письма выглядит так:
Mail::to($user)->send(new Reminder);
Давайте посмотрим на класс PHPReminder
. Сначала создадим его Artisan-командой:
shphp artisan make:mail Reminder
Теперь он находится в папке app/Mail. Посмотрим, как он выглядит изначально:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class Reminder extends Mailable
{
use Queueable, SerializesModels;
/**
* Создать новый экземпляр сообщения.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Собрать сообщение.
*
* @return $this
*/
public function build()
{
return $this->view('view.name');
}
}
Все те настройки, которые вы делали в замыканиях, теперь находятся в методе PHPbuild()
. Итак, давайте пересоберём это письмо снова:
public function build()
{
return $this->from('hello@app.com', 'Ваше приложение')
->subject('Ваше напоминание!')
->view('emails.reminder');
}
Если вы не задали тему письма, Laravel подставит её, исходя из имени класса. Если класс называется «ApplicationReminder», в теме письма будет «Application Reminder».
Передача данных
А если мы хотим передать данные в тему письма или в представление? Это происходит в конструкторе:
Mail::to($user)->send(new Reminder($event));
class Reminder extends Mailable
{
public $event;
public function __construct($event)
{
$this->event = $event;
}
public function build()
{
return $this->from('hello@app.com', 'Ваше приложение')
->subject('Напоминание о событии: ' . $this->event->name)
->view('emails.reminder');
}
}
Все «открытые» свойства нашего «посылаемого» (mailable) класса будут доступны в представлении, поэтому мы можем использовать PHP$event
в представлении:
// resources/views/emails/reminder.blade.php
<h1>{{ $event->name }} уже скоро!</h1>
<p>Lorem ipsum.</p>
А если вы захотите указать данные явно? Это можно сделать, передав массив в вызов PHPwith()
в методе PHPbuild()
:
public function build()
{
return $this->from('hello@app.com', 'Ваше приложение')
->subject('Напоминание о событии: ' . $this->event->name)
->view('emails.reminder')
->with(['title' => $this->event->name]);
}
Настройка списка рассылки
Как видите, настройка самого письма происходит в методе PHPbuild()
, а настройка адресатов происходит при вызове письма. Давайте посмотрим на PHPcc
и PHPbcc
:
Mail::to(User::find(1))
->cc(User::find(2))
->bcc(User::find(3))
->send(new Reminder);
// Эти методы также принимают коллекции
Mail::to(Users::all())
->send(new Reminder);
Текстовые представления
Есть новый метод PHPtext()
, идущий в паре с новым методом PHPview()
. Вы можете передать в него представление для текстовой версии этого письма:
public function build()
{
return $this->view('emails.reminder')
->text('emails.reminder_plain');
}
Очереди
Одна из проблем рассылки писем при выполнении вашего приложения — отправка может занимать несколько секунд. Идеальное решение — постановка в очередь. Это было просто и с предыдущим синтаксисом работы с письмами, и осталось простым с новым: просто выполните PHPMail::queue
вместо PHPMail::send
.
Mail::to($user)->queue(new Reminder);
Чтобы указать точное время для отправки, используйте PHPlater
:
$when = Carbon\Carbon::now()->addMinutes(15);
Mail::to($user)->later($when, new Reminder);
Вложения
Скоро вы привыкните к этой фразе. Всё, что вы сейчас можете выполнить в почтовых замыканиях, вы можете выполнить и в методе PHPbuild()
. В том числе PHPattach()
. Первый параметр — путь к файлу, второй необязательный параметр — массив для настройки дополнительной информации о прикреплённом файле.
public function build()
{
$this->view('emails.reminders')
->attach('/path/to/file', [
'as' => 'name.pdf',
'mime' => 'application/pdf',
]);
}
Для вложения «сырых» данных используйте PHPattachRaw()
:
public function build()
{
$this->view('emails.reminders')
->attachRaw($this->pdf, 'name.pdf', [
'mime' => 'application/pdf',
]);
}
Заключение
Mailables не является принципиально новой функцией. В ней нет ничего такого, что вы не могли сделать в Laravel раньше.
Но это одна из тех возможностей, которые делают работу с ним приятной. В своих приложениях я постоянно использую отправку писем. И я очень рад этой новой системе. Она определённо полезна.
Подробнее об этой системе вы можете прочитать в документации.