我如何判断当前交易是否将使用Doctrine 2更改任何实体? [英] How can I tell if the current transaction will change any entities with Doctrine 2?

查看:42
本文介绍了我如何判断当前交易是否将使用Doctrine 2更改任何实体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Doctrine保存用户数据,并且我想要一个last modification字段. 这是伪代码,它表示一旦用户按下Save,我想如何保存表单:

  • 开始交易
  • 做很多事情,可能查询数据库,可能不会
  • 此交易是否有任何更改
    • 修改last updated字段
  • 提交交易

有问题的部分是if anything will be changed by this transaction.学说可以给我这样的信息吗?

如何确定实体在当前交易中是否已更改?

修改

只是为了解决问题,如果提交了正确的交易后,任何实体(包括但不限于User)都将被更改,我将尝试在名为User的实体中修改名为lastUpdated的字段.换句话说,如果我开始交易并修改名为Garage的实体的nbCars字段,则我希望更新User实体的lastUpdated字段,即使该实体没有被修改.

解决方案

这是一个必要的答复,旨在纠正@ColinMorelli发布的内容(因为不允许在生命周期事件监听器中进行刷新-是的,文档中有一个位置否则会说,但是我们会摆脱掉,所以请不要这样做!).

您可以简单地收听 onFlush ,其监听器如下所示:

 use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Events;

class UpdateUserEventSubscriber implements EventSubscriber
{
    protected $user;

    public function __construct(User $user)
    {
        // assuming the user is managed here
        $this->user = $user;
    }

    public function onFlush(OnFlushEventArgs $args)
    {
        $em  = $args->getEntityManager();
        $uow = $em->getUnitOfWork();

        // before you ask, `(bool) array()` with empty array is `false`
        if (
            $uow->getScheduledEntityInsertions()
            || $uow->getScheduledEntityUpdates()
            || $uow->getScheduledEntityDeletions()
            || $uow->getScheduledCollectionUpdates()
            || $uow->getScheduledCollectionDeletions()
        ) {
            // update the user here
            $this->user->setLastModifiedDate(new DateTime());
            $uow->recomputeSingleEntityChangeSet(
                $em->getClassMetadata(get_class($this->user)), 
                $this->user
            );
        }
    }

    public function getSubscribedEvents()
    {
        return array(Events::onFlush);
    }
}
 

仅当UnitOfWork包含要提交给DB的更改时(这实际上是您可以定义为应用程序级状态事务的工作单元),这会将更改应用于已配置的User对象. /p>

您可以随时通过致电

在ORM中注册此订户.

 $user         = $entityManager->find('User', 123);
$eventManager = $entityManager->getEventManager();
$subscriber   = new UpdateUserEventSubscriber($user);

$eventManager->addEventSubscriber($subscriber);
 

I'm using Doctrine to save user data and I want to have a last modification field. Here is the pseudo-code for how I would like to save the form once the user presses Save:

  • start transaction
  • do a lot of things, possibly querying the database, possibly not
  • if anything will be changed by this transaction
    • modify a last updated field
  • commit transaction

The problematic part is if anything will be changed by this transaction. Can Doctrine give me such information?

How can I tell if entities have changed in the current transaction?

edit

Just to clear things up, I'm trying to modify a field called lastUpdated in an entity called User if any entity (including but not limited to User) will be changed once the currect transaction is commited. In other words, if I start a transaction and modify the field called nbCars of an entity called Garage, I wish to update the lastUpdated field of the User entity even though that entity hasn't been modified.

解决方案

This is a necessary reply that aims at correcting what @ColinMorelli posted (since flushing within an lifecycle event listener is disallowed - yes, there's one location in the docs that says otherwise, but we'll get rid of that, so please don't do it!).

You can simply listen to onFlush with a listener like following:

use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Events;

class UpdateUserEventSubscriber implements EventSubscriber
{
    protected $user;

    public function __construct(User $user)
    {
        // assuming the user is managed here
        $this->user = $user;
    }

    public function onFlush(OnFlushEventArgs $args)
    {
        $em  = $args->getEntityManager();
        $uow = $em->getUnitOfWork();

        // before you ask, `(bool) array()` with empty array is `false`
        if (
            $uow->getScheduledEntityInsertions()
            || $uow->getScheduledEntityUpdates()
            || $uow->getScheduledEntityDeletions()
            || $uow->getScheduledCollectionUpdates()
            || $uow->getScheduledCollectionDeletions()
        ) {
            // update the user here
            $this->user->setLastModifiedDate(new DateTime());
            $uow->recomputeSingleEntityChangeSet(
                $em->getClassMetadata(get_class($this->user)), 
                $this->user
            );
        }
    }

    public function getSubscribedEvents()
    {
        return array(Events::onFlush);
    }
}

This will apply the change to the configured User object only if the UnitOfWork contains changes to be committed to the DB (an unit of work is actually what you could probably define as an application level state transaction).

You can register this subscriber with the ORM at any time by calling

$user         = $entityManager->find('User', 123);
$eventManager = $entityManager->getEventManager();
$subscriber   = new UpdateUserEventSubscriber($user);

$eventManager->addEventSubscriber($subscriber);

这篇关于我如何判断当前交易是否将使用Doctrine 2更改任何实体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆