Во-первых, чтобы упростить дело и помочь в будущем, я бы создал интерфейс, которому должны соответствовать объекты, отслеживающие пользователей:
interface UserTracking
{
public function addedBy(UserInterface $user);
public function updatedby(UserInterface $user);
public function getAddedBy(): ?UserInterface;
public function getUpdatedBy(): ?UserInterface;
}
Затем вы можете создать Doctrine прослушиватель событий и добавьте туда компонент Security
:
class UserDataListener
{
protected $security;
public function __construct(Security $security)
{
$this->security = $security;
}
public function prePersist(LifecycleEventArgs $event): void
{
$entity = $event->getObject();
$user = $this->security->getUser();
// only do stuff if $entity cares about user data and we have a logged in user
if ( ! $entity instanceof UserTracking || null === $user ) {
return;
}
$this->setUserData($entity, $user);
}
private function preUpdate(LifecycleEventArgs $event) {
$this->prePersist($event);
}
private function setUserData(UserTracking $entity, UserInterface $user)
{
if (null === $entity->getAddedBy()) {
$entity->addedBy($user);
}
$entity->updatedBy($user);
}
}
Вам нужно соответствующим образом пометить слушателя, чтобы он срабатывал на prePersist
и preUpdate
:
services:
user_data_listener:
class: App\Infrastructure\Doctrine\Listener\UserDataListener
tags:
- { name: doctrine.event_listener, event: prePersist }
- { name: doctrine.event_listener, event: preUpdate }
Хотя вышеприведенное должно работать, Я полагаю, что вообще не очень хорошая идея использовать Doctrine события таким образом , так как вы связываете логи своего домена c с Doctrine и скрываете изменения под слоем волхвов c, который может быть неочевидным для других разработчиков, работающих с вашим приложением.
Я бы поставил createdBy
в качестве параметра конструктора и установил бы updateBy
явно при необходимости. Это просто одна строка кода каждый раз, но вы получаете ясность и выразительность, и у вас есть более простая система с меньшим количеством движущихся частей.
class FooEntity
{
private $addedBy;
private $updatedBy;
public function __construct(UserInterface $user)
{
$this->addedBy = $user;
}
public function updatedBy(UserInterface $user)
{
$this->updatedBy = $user;
}
}
Это намного лучше отражает то, что происходит с доменом, и будущие кодеры в вашему приложению не нужно искать возможные расширения, которые вы, возможно, установили и активировали, или какие события запускаются.