Symfony2/Doctrine: Get the field(s) that changed after “Loggable” entity changed

て烟熏妆下的殇ゞ 提交于 2019-12-03 08:44:01
Jean D.

The Loggable listener only saves the changesvalue for the watched properties of your entities over time.

It does not fire an event, it listens to the onFlush and postPersist doctrine events.

I think you are looking for Doctrine listeners on preUpdate and prePersist events where you can manipulate the changeset before a flush.

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

If you are using Doctrine 2.4+ you can add them easily to your entity:

Simple entity class:

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 you create the ListenerClass DogListener:

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)
    {
        //
    }
}

Clear the cache and the listener should be called when flushing.

Update

You are right about recomputeSingleEntityChangeSet which was not needed in this case. I updated the code of the listener.

The problem with the first choice (in-entity methods) is that you can't inject other services in the method. If you only need the EntityManager then yes, it is the easiest way code-wise.

With an external Listener class, you can do so.

If those 1000 fields are in several separate entities, the second type of Listener would be the most suited. You could create a NotifyOnXUpdateListener that would contain all your watch/notification logic.


Update 2

To inject services in an EntityListener declare the Listener as a service tagged with doctrine.orm.entity_listener and inject what you need.

<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>

and the listener will look like:

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)
    {
        //
    }
}

According to: How to use Doctrine Entity Listener with Symfony 2.4? it requires DoctrineBundle 1.3+

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!