При создании проекта на Symfony в сущностях Doctrine часто бывает нужно создать специальные поля для сохранения даты и времени создания записи в базе данных. Подобное сохранение можно автоматизировать для всего проекта если подобное поле создания записи есть во множестве сущностей. Тут я привожу способ автоматизации сохранения даты и времени создания.
Вся реализация сводится к созданию слушателя, который будет реагировать на событие «prePersist»
События Symfony — это механизм, который позволяет реагировать на определённые действия (например, пользователь вошёл в систему или запрос обработан). Они создаются и передаются через EventDispatcher.
Слушатели Symfony — это специальные методы или классы, которые «слушают» события и выполняют определённые действия, когда событие происходит.
prePersist — это событие Doctrine, которое вызывается перед сохранением новой записи в базу данных (до вызова метода persist). Его можно использовать для подготовки данных или выполнения действий перед сохранением.
Все что нужно создать новый слушатель
<?php
namespace App\EventListener;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
class ConfigEventListener
{
public function prePersist(LifecycleEventArgs $args): void
{
$object = $args->getObject();
$object->setCreateAt(new \DateTime('now'));
}
}
Теперь регистрируем слушатель в service.yaml
App\EventListener\ConfigEventListener:
tags:
- { name: doctrine.event_listener, event: prePersist, connection: default }
Пусть наша сущность будет такой ( для примера )
<?php
namespace App\Entity;
use App\Repository\ProductRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ProductRepository::class)]
class Product
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE)]
private ?\DateTimeInterface $createAt = null;
#[ORM\Column(length: 255)]
private ?string $title = null;
#[ORM\Column(length: 10)]
private ?string $shop = null;
#[ORM\Column]
private ?int $price = null;
#[ORM\Column]
private ?int $pricePiece = null;
public function getId(): ?int
{
return $this->id;
}
public function getCreateAt(): ?\DateTimeInterface
{
return $this->createAt;
}
public function setCreateAt(\DateTimeInterface $createAt): static
{
$this->createAt = $createAt;
return $this;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): static
{
$this->title = $title;
return $this;
}
public function getShop(): ?string
{
return $this->shop;
}
public function setShop(string $shop): static
{
$this->shop = $shop;
return $this;
}
public function getPrice(): ?int
{
return $this->price;
}
public function setPrice(int $price): static
{
$this->price = $price;
return $this;
}
public function getPricePiece(): ?int
{
return $this->pricePiece;
}
public function setPricePiece(int $pricePiece): static
{
$this->pricePiece = $pricePiece;
return $this;
}
}
Теперь при добавлении сущности в любом месте проекта, будет автоматически подставляться текущая дата и время в свойство createAt
class ProductRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Product::class);
}
public function add(string $shop, ProductDto $productDto): void
{
$product = (new Product())
->setShop($shop)
->setPrice($productDto->priceRub)
->setTitle($productDto->name);
$this->_em->persist($product);
$this->_em->flush();
}
}
