При создании проекта на 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(); } }