Laravel. Отправка почты по событию
Пусть у нас есть форма обратной связи на сайте. После отправки сообщения происходит отправка письма с данными этой формы. Но вместо того, чтобы просто отправить письмо, мы возбудим событие, перехватим его в слушателе и только после этого отправим письмо. Смысла в этом особого нет, сделано с целью изучения Laravel.
Создаем форму обратной связи
Создаем контроллер FeedbackController
:
> php artisan make:controller FeedbackController
namespace App\Http\Controllers; use stdClass; use App\Mail\FeedbackMailer; use Illuminate\Http\Request; use Illuminate\Support\Facades\Mail; class FeedbackController extends Controller { public function index() { return view('feedback.index'); } public function send(Request $request) { $request->validate([ 'name' => 'required|max:100', 'email' => 'required|email|max:100', 'message' => 'required|max:500', ]); $data = new stdClass(); $data->name = $request->name; $data->email = $request->email; $data->message = $request->message; Mail::to($data->email)->send(new FeedbackMailer($data)); return redirect()->route('feedback.index') ->with('success', 'Ваше сообщение успешно отправлено'); } }
Добавляем два маршрута в файл routes/web.php
:
Route::get('/feedback', 'FeedbackController@index')->name('feedback.index'); Route::post('/feedback', 'FeedbackController@send')->name('feedback.send');
Создаем шаблон resources/views/feedback/index.blade.php
:
@extends('layouts.app') @section('content') <h1>Обратная связь</h1> @if (session('success')) <div class="alert alert-success" role="alert"> {{ session('success') }} </div> @endif @if ($errors->any()) <div class="alert alert-danger" role="alert"> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form method="post" action="{{ route('feedback.send') }}"> @csrf <div class="form-group"> <input type="text" class="form-control" name="name" placeholder="Имя, фамилия" required maxlength="100" value="{{ old('name') ?? '' }}"> </div> <div class="form-group"> <input type="email" class="form-control" name="email" placeholder="Адрес почты" required maxlength="100" value="{{ old('email') ?? '' }}"> </div> <div class="form-group"> <textarea class="form-control" name="message" placeholder="Ваше сообщение" required maxlength="500" rows="3">{{ old('message') ?? '' }}</textarea> </div> <div class="form-group"> <button type="submit" class="btn btn-primary">Отправить</button> </div> </form> @endsection
Класс отправки почты
В Laravel каждый тип почтового сообщения (обратная связь, заказ в магазине), отправляемых приложением, представлен классом Mailable
. Эти классы хранятся в директории app/Mail
, которая будет создана при создании первого такого класса.
> php artisan make:mail FeedbackMailer
namespace App\Mail; use stdClass; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class FeedbackMailer extends Mailable { use Queueable, SerializesModels; private $data; /** * Create a new message instance. * * @return void */ public function __construct(stdClass $data) { $this->data = $data; } /** * Build the message. * * @return $this */ public function build() { return $this->from('noreply@aurora.com', 'ООО ТД АВРОРА') ->subject('Форма обратной связи') ->view('email.feedback', ['data' => $this->data]); } }
Возбуждение события при отправке формы
При отправке формы вместо отправки письма возбуждаем событие:
namespace App\Http\Controllers; use stdClass; use App\Events\FeedbackMailEvent; use Illuminate\Http\Request; class FeedbackController extends Controller { public function index() { return view('feedback.index'); } public function send(Request $request) { $request->validate([ 'name' => 'required|max:100', 'email' => 'required|email|max:100', 'message' => 'required|max:500', ]); $data = new stdClass(); $data->name = $request->name; $data->email = $request->email; $data->message = $request->message; /* * Вместо отправки письма возбуждаем событие * Mail::to($data->email)->send(new FeedbackMailer($data)); */ event(new FeedbackMailEvent($data)); return redirect()->route('feedback.index') ->with('success', 'Ваше сообщение успешно отправлено'); } }
Создание класса события
Создаем событие с помощью artisan-команды:
> php artisan make:event FeedbackMailEvent
namespace App\Events; use stdClass; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; class FeedbackMailEvent { use Dispatchable, InteractsWithSockets, SerializesModels; public $data; /** * Create a new event instance. * * @return void */ public function __construct(stdClass $data) { $this->data = $data; } /** * Get the channels the event should broadcast on. * * @return \Illuminate\Broadcasting\Channel|array */ public function broadcastOn() { return []; } }
Создание обработчика события
Создаем обработчика события с помощью artisan-команды:
> php artisan make:listener FeedbackMailListener --event="FeedbackMailEvent"
namespace App\Listeners; use App\Events\FeedbackMailEvent; use App\Mail\FeedbackMailer; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Support\Facades\Mail; class FeedbackMailListener { /** * Create the event listener. * * @return void */ public function __construct() { // ..... } /** * Handle the event. * * @param FeedbackMailEvent $event * @return void */ public function handle(FeedbackMailEvent $event) { // обрабатываем событие, то есть отправляем письмо Mail::to($event->data->email)->send(new FeedbackMailer($event->data)); } }
Регистрируем слушателя события
Открываем на редактирование файл класса EventServiceProvider
:
namespace App\Providers; use App\Events\FeedbackMailEvent; use App\Listeners\FeedbackMailListener; use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Event; class EventServiceProvider extends ServiceProvider { /** * The event listener mappings for the application. * * @var array */ protected $listen = [ Registered::class => [ SendEmailVerificationNotification::class, ], FeedbackMailEvent::class => [ // событие при отправке формы FeedbackMailListener::class, // слушатель этого события ] ]; /** * Register any events for your application. * * @return void */ public function boot() { parent::boot(); // ..... } }
- Laravel. Наблюдатели за событиями Eloquent
- Laravel. Отправка письма из приложения
- Laravel. События, слушатели и подписчики
- Laravel. Работа с БД. Часть вторая — конструктор запроса
- Laravel. Работа с БД. Часть первая — сырой запрос
- Laravel. Аксессоры и мутаторы
- Laravel. Контракт, сервис-провайдер и фасад
Поиск: Laravel • PHP • Web-разработка • Класс • Событие • Теория • Форма • Фреймворк