[英]Symfony & Doctrine: Log changes in a table with an Event Listener
在 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() 以無限循環結束,並且出現此錯誤:
PHP 致命錯誤:達到“256”的最大函數嵌套級別,正在中止! 在第 187 行的 /var/www/sellbytel/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php
所以我的問題是:如果可能的話,如何從 EventListener 保存數據庫中的更改? 如果沒有,是否有創建此日志的解決方法?
如果User
username 或 password 字段發生更改,日志將寫入UserAudit
表,因此與數據庫觸發器的邏輯相同。 您可以根據自己的需要進行調整。
參考: http : //www.inanzzz.com/index.php/post/ew0r/logging-field-changes-with-a-trigger-like-event-listener-for-auditing-purposes
服務.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();
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.