Symfony2/Doctrine:获取“Loggable”实体更改后更改的字段

2024-03-04

在 Symfony2 项目中,我使用 Loggable Doctrine 扩展。

I saw https://github.com/Atlantic18/DoctrineExtensions/blob/master/lib/Gedmo/Loggable/LoggableListener.php有一个 LoggableListener。

当可记录实体中的(可记录)字段发生更改时,是否确实存在会触发的事件?如果是这样,有没有办法获取触发它的字段列表?

我想象一个实体的情况,假设有 10 个字段,其中 3 个可记录。对于这 3 个值中的每一个,如果它们的值发生变化,我想执行一些操作,因此如果这 3 个值发生变化,将执行 3 个操作。

任何想法?

谢谢你!

EDIT

阅读下面的评论并阅读有关学说事件的文档后,我明白有 3 个选择:

1)使用生命周期回调 http://doctrine-orm.readthedocs.org/en/latest/reference/events.html#lifecycle-callbacks甚至直接在实体层面有参数 http://doctrine-orm.readthedocs.org/en/latest/reference/events.html#lifecycle-callbacks-event-argument如果我使用原则 >2.4

2)我可以监听并订阅生命周期事件 http://doctrine-orm.readthedocs.org/en/latest/reference/events.html#listening-and-subscribing-to-lifecycle-events,但在这种情况下,文档说"Lifecycle events are triggered for all entities. It is the responsibility of the listeners and subscribers to check if the entity is of a type it wants to handle."

3)按照您的建议进行操作,即使用实体监听器 http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#entity-listeners,您可以在实体级别定义将“附加”到该类的侦听器。

即使第一个解决方案看起来更简单,我读到“您还可以使用此侦听器来实现对所有已更改字段的验证。当需要调用昂贵的验证时,这比使用生命周期回调更有效”。什么被认为是“昂贵的验证?”。

就我而言,我必须执行的操作类似于“如果实体 Y 的字段 X 发生更改,则在通知表上添加一条通知,说明“用户 Z 将 X(Y) 的值从 A 更改为 B”

考虑到我有大约 1000 个这样的字段,哪种方法是最合适的?

EDIT2

为了解决我的问题,我尝试将 service_container 服务注入侦听器中,以便我可以访问调度程序来调度一个新事件,该事件可以执行我需要的新实体的持久化。但我怎样才能做到这一点呢?

我尝试了通常的方法,将以下内容添加到 service.yml 中

app_bundle.project_tolereances_listener:
    class: AppBundle\EventListener\ProjectTolerancesListener
    arguments: [@service_container] 

当然,我向监听器添加了以下内容:

protected $container;

public function __construct(ContainerInterface $container)
{
    $this->container = $container;
}

但我得到以下信息:

Catchable Fatal Error: Argument 1 passed to AppBundle\ProjectEntityListener\ProjectTolerancesListener::__construct() must be an instance of AppBundle\ProjectEntityListener\ContainerInterface, none given, called in D:\provarepos\user\vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\DefaultEntityListenerResolver.php on line 73 and defined

任何想法?


Loggable 侦听器仅保存实体的受监视属性随时间的变化值。

它不会触发事件,它会监听onFlush and postPersist教义事件。

我认为您正在寻找 preUpdate 和 prePersist 事件的 Doctrine 侦听器,您可以在其中操作更改集flush.

see: http://doctrine-orm.readthedocs.org/en/latest/reference/events.html http://doctrine-orm.readthedocs.org/en/latest/reference/events.html

如果您使用的是 Doctrine 2.4+,您可以轻松地将它们添加到您的实体中:

简单实体类:

namespace Your\Namespace\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 *  @ORM\Entity
 *  @ORM\EntityListeners({"Your\Namespace\Listener\DogListener"})
 */
class Dog
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    private $name;

    /**
     * @ORM\Column(type="integer")
     */
    private $age;

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param int $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param string $name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * @return int
     */
    public function getAge()
    {
        return $this->age;
    }

    /**
     * @param int $age
     */
    public function setAge($age)
    {
        $this->age = $age;
    }
}

Then in Your\Namespace\Listener您创建 ListenerClassDogListener:

namespace Your\Namespace\Listener;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Your\Namespace\Entity\Dog;

class DogListener
{
    public function preUpdate(Dog $dog, PreUpdateEventArgs $event)
    {         
        if ($event->hasChangedField('name')) {                
            $updatedName = $event->getNewValue('name'). ' the dog';
            $dog->setName($updatedName);         
        }

        if ($event->hasChangedField('age')) {
            $updatedAge = $event->getNewValue('age') % 2;
            $dog->setAge($updatedAge);
        }

    }

    public function prePersist(Dog $dog, LifecycleEventArgs $event)
    {
        //
    }
}

清除缓存,刷新时应调用监听器。

Update

您对 recomputeSingleEntityChangeSet 的看法是正确的,在本例中不需要它。我更新了监听器的代码。

第一个选择(实体内方法)的问题是您无法在该方法中注入其他服务。 如果您只需要 EntityManager,那么是的,这是最简单的代码方式。

通过外部 Listener 类,您可以做到这一点。

如果这 1000 个字段位于多个单独的实体中,则第二种类型的侦听器将是最合适的。你可以创建一个NotifyOnXUpdateListener这将包含您所有的手表/通知逻辑。


Update 2

要在 EntityListener 中注入服务,请将侦听器声明为标记为的服务doctrine.orm.entity_listener并注入你需要的东西。

<service id="app.entity_listener.your_service" class="Your\Namespace\Listener\SomeEntityListener">
        <argument type="service" id="logger" />
        <argument type="service" id="event_dispatcher" />
        <tag name="doctrine.orm.entity_listener" />
</service>

听众将如下所示:

class SomeEntityListener
{
    private $logger;
    private $dispatcher;

    public function __construct(LoggerInterface $logger, EventDispatcherInterface $dispatcher)
    {
        $this->logger = $logger;
        $this->dispatcher = $dispatcher;
    }

    public function preUpdate(Block $block, PreUpdateEventArgs $event)
    {
        //
    }
}

根据:如何在 Symfony 2.4 中使用 Doctrine 实体监听器? https://stackoverflow.com/questions/22114239/how-to-use-doctrine-entity-listener-with-symfony-2-4它需要 DoctrineBundle 1.3+

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Symfony2/Doctrine:获取“Loggable”实体更改后更改的字段 的相关文章

随机推荐