我有一个onFlush()事件工作正常,但我需要做的是将其转换为preFlush()或preUpdate()都可以接受。我做了preFlush()但由于某种原因它没有做任何事情。甚至没有错误。我错过了什么?
TEST:我将exit
放在preFlush()
中以查看是否正在调用它。结果是: 1 所以foreach()
永远不会运行!这是一个空数组。我还测试了preUpdate(),其中的所有行都被破坏但没有插入数据。
public function preFlush(PreFlushEventArgs $args)
{
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
echo '1';
foreach ($uow->getScheduledEntityUpdates() as $entity) {
echo '2';
if ($entity instanceof User) {
echo '3';
}
}
exit;
}
我在阅读documentation后创建了它们。
service.yml
services:
entity.event_listener.user:
class: Site\FrontBundle\EventListener\Entity\UserListener
tags:
- { name: doctrine.event_listener, event: preUpdate }
- { name: doctrine.event_listener, event: onFlush }
- { name: doctrine.event_listener, event: preFlush }
使用onFlush()示例:
class UserListener
{
public function onFlush(OnFlushEventArgs $args)
{
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
foreach ($uow->getScheduledEntityUpdates() as $entity) {
if ($entity instanceof User) {
$userLog = new UserLog();
$userLog->setDescription($entity->getId() . ' being updated.');
$em->persist($userLog);
// Instead of $em->flush() cos we're already in flush process
$userLogMetadata = $em->getClassMetadata(get_class($userLog));
$uow->computeChangeSet($userLogMetadata, $userLog);
}
}
}
}
不工作preFlush()示例:
class UserListener
{
public function preFlush(PreFlushEventArgs $args)
{
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
foreach ($uow->getScheduledEntityUpdates() as $entity) {
if ($entity instanceof User) {
$userLog = new UserLog();
$userLog->setDescription($entity->getId() . ' being updated.');
$em->persist($userLog);
// Instead of $em->flush() cos we're already in flush process
$userLogMetadata = $em->getClassMetadata(get_class($userLog));
$uow->computeChangeSet($userLogMetadata, $userLog);
}
}
}
}
不工作preUpdate()示例
class UserListener
{
public function preUpdate(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
if ($entity instanceof User) {
$userLog = new UserLog();
$userLog->setDescription($entity->getId() . ') been updated.');
$em = $args->getEntityManager();
$em->persist($userLog);
$userLogMetadata = $em->getClassMetadata(get_class($userLog));
$uow->computeChangeSet($userLogMetadata, $userLog);
}
}
}
答案 0 :(得分:10)
<强> SOLUTION:强>
诀窍是,在preUpdate()
事件中postFlush()
之后保持不变。
注意: 虽然这可能不是最佳解决方案,但它可以回答问题,但可以使用事件订阅者或简单onFlush()
- 来完成;事件监听器中的$uow->getScheduledEntityUpdates()
。
<强> Service.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();
}
}
}
答案 1 :(得分:2)
阅读文档,
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);
}
}
答案 2 :(得分:1)
亲爱的 BentCoder :
我正在使用Symfony 2.7版本。在您的帖子等事件监听器中使用 $ em-&gt; flush 时,会发生以下错误:
click-here-to-see-bug-description
而且,这是我的解决方案:
的 Service.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();
}
}
}
希望这会对某人有所帮助!