问题描述
我正在开发我的第一个Symfony 4应用程序,并从Symfony 2+和symfony 3+迁移。
I am developing my first Symfony 4 application and I migrating from Symfony 2+ and symfony 3+.
现在我正在开发一个后端,所有我的实体类具有 addedBy()
和 updatedBy()
方法,我需要在其中记录当前登录的管理员。
Right now I am developing a back-end and all of my entity classes have a addedBy()
and updatedBy()
methods where I need to record the current logged in administrator.
我想要一个类似事件监听器的东西,而不必在所有控制器中都设置这些方法。
I would like to have something like an event listener where I do not have to set those methods in all of my controllers.
如何完成此操作?
推荐答案
首先,为了简化流程并帮助我创建一个接口该用户跟踪实体将需要遵守:
First, to simplify matters and help down the road I would create an interface this user-tracking entities would need to comply with:
interface UserTracking
{
public function addedBy(UserInterface $user);
public function updatedby(UserInterface $user);
public function getAddedBy(): ?UserInterface;
public function getUpdatedBy(): ?UserInterface;
}
然后您可以创建一个Doctrine事件侦听器,并注入 Security
组件:
Then you can create a Doctrine event listener, and inject the Security
component there:
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
上触发:
You'd need to tag the listener appropriately, so it triggers on prePersist
and 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事件通常不是一个好主意,因为您要将域逻辑与Doctrine结合在一起,并且隐藏了一层不可思议的变化,对于使用您的应用程序的其他开发人员来说,这可能不是立即可见的。
While the above should work, I believe it's generally not such a great idea to use Doctrine events this way, since you are coupling your domain logic with Doctrine, and are hiding changing under a layer of magic that may not be immediately evident for other developers working with your application.
我将 createdBy
作为构造函数参数,并在需要时显式设置 updateBy
。每次只是一行代码,但是您可以获得清晰和表达力,并且系统更简单,移动部件更少。
I'd put the createdBy
as a constructor parameter, and set updateBy
explicitly when needed. It's just one line of code each time, but you gain clarity and expressiveness, and you have a simpler system with less moving parts.
class FooEntity
{
private $addedBy;
private $updatedBy;
public function __construct(UserInterface $user)
{
$this->addedBy = $user;
}
public function updatedBy(UserInterface $user)
{
$this->updatedBy = $user;
}
}
这更好地表达了域的状况,并且您的应用程序中将来的编码人员不必挖掘您可能已安装和启用的扩展名或正在触发的事件。
This expresses much better what's happening with the domain, and future coders in your application do no have to dig around for the possible extensions you may have installed and enabled, or what events are being triggered.
这篇关于如何使当前用户进入我的实体类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!