Событие OnFlush
Событие OnFlush возникает в Doctrine
после того, как EntityManager вычислил
изменения сущностей, но до того, как они
будут записаны в базу данных. Обработчик
этого события получает доступ к UnitOfWork
и может добавить новые сущности в очередь
на вставку, изменение или удаление.
В отличие от событий жизненного цикла сущности,
таких как PrePersist или PreUpdate,
событие OnFlush не привязано к конкретному
классу сущности. Оно регистрируется через
сервис-подписчик на событие Doctrine\ORM\Events::onFlush.
Обработчик события OnFlush должен
реализовать метод onFlush, который
принимает объект OnFlushEventArgs.
Через него можно получить EntityManager
и UnitOfWork, чтобы управлять изменениями.
Синтаксис
<?php
public function onFlush(OnFlushEventArgs $args): void
{
$em = $args->getObjectManager();
$uow = $em->getUnitOfWork();
// work with $uow->getScheduledEntityInsertions()
// $uow->getScheduledEntityUpdates()
// $uow->getScheduledEntityDeletions()
}
?>
Пример
Давайте создадим сущность Article
с полями title и createdAt:
<?php
namespace App\Entity;
use App\Repository\ArticleRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ArticleRepository::class)]
class Article
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $title = null;
#[ORM\Column]
private ?\DateTimeImmutable $createdAt = null;
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): static
{
$this->title = $title;
return $this;
}
public function getCreatedAt(): ?\DateTimeImmutable
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeImmutable $createdAt): static
{
$this->createdAt = $createdAt;
return $this;
}
}
?>
Теперь создадим подписчик на событие OnFlush,
который автоматически проставляет дату создания
для новых статей:
<?php
namespace App\EventListener;
use App\Entity\Article;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Events;
class ArticleOnFlushListener
{
public function onFlush(OnFlushEventArgs $args): void
{
$em = $args->getObjectManager();
$uow = $em->getUnitOfWork();
foreach ($uow->getScheduledEntityInsertions() as $entity) {
if ($entity instanceof Article) {
if ($entity->getCreatedAt() === null) {
$entity->setCreatedAt(new \DateTimeImmutable());
}
$uow->recomputeSingleEntityChangeSet(
$em->getClassMetadata(Article::class),
$entity
);
}
}
}
}
?>
Зарегистрируем подписчик в конфигурации сервисов:
services:
App\EventListener\ArticleOnFlushListener:
tags:
- { name: doctrine.event_listener, event: onFlush }
Пример
Давайте используем подписчик в контроллере и создадим новую статью:
<?php
namespace App\Controller;
use App\Entity\Article;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class ArticleController extends AbstractController
{
#[Route('/article/create', name: 'article_create')]
public function create(EntityManagerInterface $em): Response
{
$article = new Article();
$article->setTitle('abcde');
$em->persist($article);
$em->flush();
return new Response('created at: ' . $article->getCreatedAt()->format('Y-m-d H:i:s'));
}
}
?>
Результат выполнения кода:
created at: 2026-01-01 12:00:00
Пример
Давайте в событии OnFlush добавим
изменение существующей сущности. Например,
при обновлении статьи будем добавлять
к заголовку префикс:
<?php
namespace App\EventListener;
use App\Entity\Article;
use Doctrine\ORM\Event\OnFlushEventArgs;
class ArticleOnFlushListener
{
public function onFlush(OnFlushEventArgs $args): void
{
$em = $args->getObjectManager();
$uow = $em->getUnitOfWork();
foreach ($uow->getScheduledEntityUpdates() as $entity) {
if ($entity instanceof Article) {
$entity->setTitle('user: ' . $entity->getTitle());
$uow->recomputeSingleEntityChangeSet(
$em->getClassMetadata(Article::class),
$entity
);
}
}
}
}
?>
Результат выполнения кода после обновления статьи:
user: abcde