Skip to content

Instantly share code, notes, and snippets.

@BurningDog
Last active September 12, 2024 13:47
Show Gist options
  • Select an option

  • Save BurningDog/8d1ea4843759fdd338a1bde081ea0531 to your computer and use it in GitHub Desktop.

Select an option

Save BurningDog/8d1ea4843759fdd338a1bde081ea0531 to your computer and use it in GitHub Desktop.
EntityListenerPostUpdateTrait
<?php
namespace App\Command;
class AuthorChangedEvent
{
private int $bookId;
public function __construct(Book $book, private array $changedFields, private \DateTime $createdAt)
{
$this->bookId = $book->getId();
}
public function getBookId(): int
{
return $this->bookId;
}
public function getCreatedAt(): \DateTime
{
return $this->createdAt;
}
public function getChangedFields(): array
{
return $this->changedFields;
}
}
<?php
namespace App\Doctrine\EventListener;
use App\Command\AuthorChangedEvent;
use App\Entity\Book;
use App\Doctrine\EventListener\Trait\EntityListenerPostUpdateTrait;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Symfony\Component\Messenger\MessageBusInterface;
class BookListener
{
use EntityListenerPostUpdateTrait;
public function __construct(
private readonly MessageBusInterface $commandBus,
MessageBusInterface $eventBus,
) {
$this->initEntityListenerPostUpdateTrait($eventBus);
}
public function preUpdate(Book $book, PreUpdateEventArgs $eventArgs): void
{
if ($eventArgs->hasChangedField('author')) {
$this->changedFields[] = 'author';
}
if (count($this->changedFields) > 0) {
$this->addEvent(new AuthorChangedEvent($book, $this->changedFields, new \DateTime()));
}
}
}
<?php
namespace App\Doctrine\EventListener\Trait;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Symfony\Component\Messenger\MessageBusInterface;
trait EntityListenerPostUpdateTrait
{
private MessageBusInterface $eventBus;
private ArrayCollection $events;
private array $changedFields;
private function initEntityListenerPostUpdateTrait(MessageBusInterface $eventBus)
{
$this->eventBus = $eventBus;
$this->events = new ArrayCollection();
$this->changedFields = [];
}
/**
* Add events to the events collection.
*/
protected function addEvent(): void
{
$this->events->add(...func_get_args());
}
public function postUpdate(): void
{
foreach ($this->events as $event) {
$this->eventBus->dispatch($event);
}
// Reset events after dispatching, otherwise if an entity gets pesisted again before the end of the request,
// the events will be dispatched again.
$this->events = new ArrayCollection();
}
private function addChangedField(string $changedField, PreUpdateEventArgs $eventArgs): void
{
$this->changedFields[] = [
$changedField => [
'old' => $eventArgs->getOldValue($changedField),
'new' => $eventArgs->getNewValue($changedField),
],
];
}
}
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
App\Doctrine\EventListener\BookListener:
tags:
- { name: doctrine.orm.entity_listener, events: ['preUpdate', 'postUpdate'] }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment