Laravel. Отправка почты по событию

19.11.2020

Теги: LaravelPHPWeb-разработкаКлассСобытиеТеорияФормаФреймворк

Пусть у нас есть форма обратной связи на сайте. После отправки сообщения происходит отправка письма с данными этой формы. Но вместо того, чтобы просто отправить письмо, мы возбудим событие, перехватим его в слушателе и только после этого отправим письмо. Смысла в этом особого нет, сделано с целью изучения 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 • PHP • Web-разработка • Класс • Событие • Теория • Форма • Фреймворк

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.