Создание preUpdate или событие preFlush с прослушивателей событий
у меня есть событие onFlush (), которое отлично работает, но что мне нужно сделать, это превратить его в preFlush () или preUpdate (). Я preFlush (), но почему-то не делает ничего. Ни единой ошибки. Что я упускаю?
3 ответов
устранение:
фокус в том, чтобы упорствовать после preUpdate()
внутри postFlush()
событие.
Примечание: хотя это может быть не лучшим решением, он отвечает на вопрос, однако это может быть сделано с подписчиком события или просто onFlush()
->$uow->getScheduledEntityUpdates()
в Прослушивателе событий.
сервис.в формате YML
services:
entity.event_listener.user_update:
class: Site\FrontBundle\EventListener\Entity\UserUpdateListener
tags:
- { name: doctrine.event_listener, event: preUpdate }
- { name: doctrine.event_listener, event: postFlush }
Прослушивателя Событий
<?php
namespace Site\FrontBundle\EventListener\Entity;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PostFlushEventArgs;
use Site\FrontBundle\Entity\User;
use Site\FrontBundle\Entity\UserLog;
class UserUpdateListener
{
private $log = array();
public function preUpdate(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
// False check is compulsory otherwise duplication occurs
if (($entity instanceof User) === false) {
$userLog = new UserLog();
$userLog->setDescription($entity->getId() . ' being updated.');
$this->log[] = $userLog;
}
}
public function postFlush(PostFlushEventArgs $args)
{
if (! empty($this->log)) {
$em = $args->getEntityManager();
foreach ($this->log as $log) {
$em->persist($log);
}
$em->flush();
}
}
}
чтение документации,
http://doctrine-orm.readthedocs.org/en/latest/reference/events.html#onflush
он не упоминает об этом preFlush
имеет информацию об изменениях (я имею в виду entityManager)
если вы посмотрите на Doctrine\ORM\UnitOfWork
вы видите, что наборы изменений вычисляются после preFlush
событие, поэтому вы должны использовать onFlush
если вы хотите взаимодействовать с измененными объектами
// Raise preFlush
if ($this->evm->hasListeners(Events::preFlush)) {
$this->evm->dispatchEvent(Events::preFlush, new PreFlushEventArgs($this->em));
}
// Compute changes done since last commit.
if ($entity === null) {
$this->computeChangeSets();
} elseif (is_object($entity)) {
$this->computeSingleEntityChangeSet($entity);
} elseif (is_array($entity)) {
foreach ($entity as $object) {
$this->computeSingleEntityChangeSet($object);
}
}
дорогие BentCoder:
Я использую версию Symfony 2.7. При использовании $em - >flush в прослушивателе событий, как ваш пост, эта ошибка произошла:
click-here-to-see-bug-description
и, это мое решение:
сервис.в формате YML
services:
app.listener:
class: AppBundle\EventListener\DoctrineListener
arguments: ["@service_container"]
tags:
- { name: doctrine.event_listener, event: preUpdate, method: preUpdate }
- { name: doctrine.event_listener, event: postUpdate, method: postUpdate }
Прослушивателя Событий
namespace AppBundle\EventListener;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\ORM\Event\LifecycleEventArgs;
use AppBundle\Entity;
/**
* Log activity on website
* Class DoctrineListener
* @package AppBundle\EventListener
*/
class DoctrineListener
{
/**
* @var ContainerInterface
*/
private $_container;
/**
* @var Array
*/
private $_activities;
/**
* DoctrineListener constructor.
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->_container = $container;
}
/**
* @param LifecycleEventArgs $args
*/
public function preUpdate(LifecycleEventArgs $args)
{
$entityManager = $args->getEntityManager();
$entity = $args->getEntity();
$activityEntity = new Entity\Activity();
$activityEntity->setAction(Entity\Activity::ACTION_EDIT);
$activityEntity->setActionAt(new \DateTime());
$activityEntity->setIpAddress($this->_container->get('request')->getClientIp());
switch (true) {
case $entity instanceof Entity\Goods:
$repository = $entityManager->getRepository('AppBundle:Goods');
$activityEntity->setType(Entity\Activity::TYPE_GOODS);
$message = 'User: <strong>%s</strong> sửa mẫu hàng hóa <strong>%s</strong>';
break;
default:
return;
}
if (isset($repository) && $args->getEntityChangeSet()) {
$user = $this->_container->get('security.context')->getToken()->getUser();
$recordBefore = clone $entity;
foreach ($args->getEntityChangeSet() as $key => $value) {
$method = 'set'.ucfirst($key);
$recordBefore->$method($value[0]);
}
$activityEntity->setFosUser($user);
$activityEntity->setRecordBefore(serialize($recordBefore));
$activityEntity->setRecordAfter(serialize($entity));
$activityEntity->setMessage(
sprintf(
$message,
$user->getUserProfile()->getFullName(),
(string) $recordBefore
)
);
$this->_activities[] = $activityEntity;
}
return;
}
/**
* @param LifecycleEventArgs $args
*/
public function postUpdate(LifecycleEventArgs $args)
{
if (sizeof($this->_activities)) {
$entityManager = $args->getEntityManager();
foreach ($this->_activities as $activity) {
$entityManager->persist($activity);
}
$entityManager->flush();
}
}
}
надеюсь, что это поможет кому-то!