В 12-ом уроке мы разберем одну из возможностей Symfony, это работу с событиями. Этот урок станет важным шагом в понимании гибкости и расширяемости фреймворка. Мы научимся создавать кастомные события, настраивать слушателей и подписчиков, а также реализуем практический пример отправки email после регистрации пользователя.
Что такое EventDispatcher?
В Symfony за обработку событий отвечает компонент EventDispatcher. Это «посредник», который связывает события (например, «пользователь зарегистрировался») с их обработчиками (например, «отправить email»).
Его ключевые задачи:
- Декомпозиция кода. Разделение логики на независимые части.
- Гибкость. Можно добавлять или удалять обработчики без изменения основного кода.
- Стандартизация. Единый способ реагировать на действия в приложении.
Как это работает?
- Событие (Event) генерируется в определенный момент (например, после сохранения пользователя).
- EventDispatcher получает событие и ищет все связанные с ним слушатели (Listeners) или подписчики (Subscribers).
- Слушатели выполняют свою логику в ответ на событие.
Создание кастомных событий
Давай создадим свое событие. Предположим, мы хотим отправлять email после регистрации пользователя.
Шаг 1: Создаем класс события
Кастомное событие это обычный PHP-класс, который хранит данные, связанные с событием. Создадим UserRegisteredEvent:
// src/Event/UserRegisteredEvent.php namespace App\Event; use Symfony\Contracts\EventDispatcher\Event; use App\Entity\User; class UserRegisteredEvent extends Event { public const NAME = 'user.registered'; private $user; public function __construct(User $user) { $this->user = $user; } public function getUser(): User { return $this->user; } }
NAME— уникальное имя события.- Конструктор принимает объект пользователя, который будет передан слушателям.
Шаг 2: Генерируем событие
Теперь вызовем событие после регистрации пользователя. Например в контроллере:
// src/Controller/RegistrationController.php use App\Event\UserRegisteredEvent; use Symfony\Component\EventDispatcher\EventDispatcherInterface; class RegistrationController extends AbstractController { public function register( Request $request, EventDispatcherInterface $dispatcher ): Response { // ... логика регистрации // Создаем и диспатчим событие $event = new UserRegisteredEvent($user); $dispatcher->dispatch($event, UserRegisteredEvent::NAME); return $this->redirectToRoute('home'); } }
Метод dispatch() принимает объект события и его имя (опционально, но рекомендуется для ясности).
Слушатели (Listeners) или Подписчики (Subscribers)
В Symfony есть два подхода к обработке событий. Разберем их различия.
Слушатели (Listeners)
Слушатель это PHP-класс или функция, которая реагирует на конкретное событие.
Пример слушателя для отправки email:
// src/EventListener/SendWelcomeEmailListener.php namespace App\EventListener; use App\Event\UserRegisteredEvent; use Symfony\Component\Mailer\MailerInterface; class SendWelcomeEmailListener { private $mailer; public function __construct(MailerInterface $mailer) { $this->mailer = $mailer; } public function onUserRegistered(UserRegisteredEvent $event): void { $user = $event->getUser(); // ... логика отправки email } }
Регистрируем слушатель в config/services.yaml:
services: App\EventListener\SendWelcomeEmailListener: tags: - { name: kernel.event_listener, event: user.registered, method: onUserRegistered }
Подписчики (Subscribers)
Подписчик это класс, который реализует интерфейс EventSubscriberInterface и определяет, на какие события он подписан.
Пример подписчика для логирования:
// src/EventSubscriber/LogActivitySubscriber.php namespace App\EventSubscriber; use App\Event\UserRegisteredEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class LogActivitySubscriber implements EventSubscriberInterface { public static function getSubscribedEvents(): array { return [ UserRegisteredEvent::NAME => 'logUserRegistration', ]; } public function logUserRegistration(UserRegisteredEvent $event): void { $user = $event->getUser(); // ... логика логирования } }
Symfony автоматически обнаружит подписчик благодаря интерфейсу.
В чем разница?
| Критерий | Слушатели | Подписчики |
|---|---|---|
| Регистрация | Через конфиг или атрибуты | Через интерфейс EventSubscriberInterface |
| Гибкость | Подходит для простых сценариев | Удобен для группировки связанных событий |
| Сложность | Проще | Требует реализации интерфейса |
Пример отправки email после регистрации
Давай реализуем полноценный пример с отправкой приветственного письма.
Шаг 1: Настраиваем Mailer
Убедись, что в .env указаны настройки почты:
MAILER_DSN=smtp://user:pass@smtp.example.com:port
Шаг 2: Дополняем слушатель
Модифицируем SendWelcomeEmailListener:
// src/EventListener/SendWelcomeEmailListener.php use Symfony\Bridge\Twig\Mime\TemplatedEmail; public function onUserRegistered(UserRegisteredEvent $event): void { $user = $event->getUser(); $email = (new TemplatedEmail()) ->to($user->getEmail()) ->subject('Добро пожаловать!') ->htmlTemplate('emails/welcome.html.twig') ->context([ 'user' => $user, ]); $this->mailer->send($email); }
Шаг 3: Создаем шаблон письма
templates/emails/welcome.html.twig:
<h1>Привет, {{ user.username }}!</h1> <p>Спасибо за регистрацию на нашем сайте.</p>
Практические задания
Закрепим материал задачами.
Задача 1: Создайте событие «Комментарий добавлен»
- Создайте класс
CommentCreatedEvent. - Генерируйте событие после сохранения комментария в базе.
- Напишите слушатель, который отправляет уведомление администратору.
Задача 2: Реализуйте подписчик для логирования
- Создайте подписчик
LoggingSubscriber. - Подпишитесь на события
kernel.exceptionиuser.registered. - Логируйте информацию о событиях в файл
var/log/events.log.
Решения для задачи 1:
// src/Event/CommentCreatedEvent.php namespace App\Event; use Symfony\Contracts\EventDispatcher\Event; use App\Entity\Comment; class CommentCreatedEvent extends Event { public const NAME = 'comment.created'; public function __construct(private Comment $comment) {} public function getComment(): Comment { return $this->comment; } }
Сегодня мы разобрали:
- Как работает EventDispatcher в Symfony.
- Создание кастомных событий и их диспетчеризацию.
- Разницу между слушателями и подписчиками.
- Реальный пример отправки email после регистрации.
Эти знания помогут создавать расширяемые и легко поддерживаемые приложения. Хочешь освоить Symfony? Полный курс по Symfony для начинающих
Поддержка автора осуществляется с помощью специальной формы ниже, предоставленной сервисом «ЮMoney». Все платёжные операции выполняются на защищённой странице сервиса, что обеспечивает их корректность и полную безопасность.


