在Symfony 3项目中,我有一个实体,我想审核一些属性的变化,所以我可以创建一个事件监听器来存储它们。
实体或多或少如下:
EventListener如下所示
/**
* @param OnFlushEventArgs $args
*/
public function onFlush(OnFlushEventArgs $args)
{
/** @var ReceivedEmail $entity */
$entityManager = $args->getEntityManager();
$unitOfWork = $entityManager->getUnitOfWork();
$updates = $unitOfWork->getScheduledEntityUpdates();
foreach ($updates as $entity) {
if ($entity instanceof ReceivedEmail) {
$changes = $unitOfWork->getEntityChangeSet($entity);
$this->receivedEmailChanges[] = $this->receivedEmailChangeManager
->getReceivedEmailChanges($entity, $changes);
}
}
}
public function postFlush(PostFlushEventArgs $args)
{
$em = $args->getEntityManager();
$i = 0;
foreach($this->receivedEmailChanges as $receivedEmailChange) {
$em->persist($receivedEmailChange);
unset($this->receivedEmailChanges[$i]);
$i++;
}
if ($i > 0) {
$em->flush();
}
}
问题是在postFlush方法上调用$ entityManager-> flush()会在infinte循环中结束并出现此错误:
PHP致命错误:达到了'256'的最大函数嵌套级别, 中止!在 /var/www/sellbytel/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php 在第187行
所以我的问题是:如果可能的话,如何从EventListener中保存数据库中的更改?如果没有,是否有解决方法来创建此日志?
谢谢!
答案 0 :(得分:1)
如果User
的用户名或密码字段发生更改,则会将日志写入UserAudit
表,其逻辑与数据库触发器相同。您可以根据需要进行调整。
<强> services.yml 强>
services:
application_backend.event_listener.user_entity_audit:
class: Application\BackendBundle\EventListener\UserEntityAuditListener
arguments: [ @security.context ]
tags:
- { name: doctrine.event_listener, event: preUpdate }
- { name: doctrine.event_listener, event: postFlush }
<强>监听强>
namespace Application\BackendBundle\EventListener;
use Application\BackendBundle\Entity\User;
use Application\BackendBundle\Entity\UserAudit;
use Doctrine\ORM\Event\PostFlushEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Symfony\Component\Security\Core\SecurityContextInterface;
class UserEntityAuditListener
{
private $securityContext;
private $fields = ['username', 'password'];
private $audit = [];
public function __construct(SecurityContextInterface $securityContextInterface)
{
$this->securityContext = $securityContextInterface;
}
public function preUpdate(PreUpdateEventArgs $args) // OR LifecycleEventArgs
{
$entity = $args->getEntity();
if ($entity instanceof User) {
foreach ($this->fields as $field) {
if ($args->getOldValue($field) != $args->getNewValue($field)) {
$audit = new UserAudit();
$audit->setField($field);
$audit->setOld($args->getOldValue($field));
$audit->setNew($args->getNewValue($field));
$audit->setUser($this->securityContext->getToken()->getUsername());
$this->audit[] = $audit;
}
}
}
}
public function postFlush(PostFlushEventArgs $args)
{
if (! empty($this->audit)) {
$em = $args->getEntityManager();
foreach ($this->audit as $audit) {
$em->persist($audit);
}
$this->audit = [];
$em->flush();
}
}
}