In a Symfony2 project I'm using the Loggable Doctrine Extension.
I saw that there is a LoggableListener.
Is there indeed an event that gets fired when a (loggable) field in a loggable entity changes? If it is so, is there a way to get the list of fields that triggered it?
I'm imagining the case of an entity with, let's say 10 fields of which 3 loggable. For each of the 3 I want to perform some actions if they change value, so 3 actions will be performed if the 3 of them change.
Any idea?
Thank you!
EDIT
After reading the comment below and reading the docs on doctrine's events I understood have 3 options:
1) using lifecycle callbacks directly at the entity level even with arguments if I'm using doctrine >2.4
2) I can listen and subscribe to Lifecycle Events, but in this case the docs say that "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) doing what you suggest, which is using an Entity listener, where you can define at the entity level which is the listener that is going to be "attached" to the class.
Even if the first solution seems easier, I read that "You could also use this listener to implement validation of all the fields that have changed. This is more efficient than using a lifecycle callback when there are expensive validations to call". What's considered an "expensive validation?".
In my case what I have to perform is something like "if field X of entity Y changed than add a notification on the notification table saying "user Z changed the value of X(Y) from A to B"
Which would be the most suitable approach, considering that I have around 1000 fields like those?
EDIT2
To solve my problem I'm trying to inject the service_container service inside the listener, so that I can have access to the dispatcher to dispatch a new event which can perform the persist of new entity I need. But how can I do that?
I tried the usual way, I add the following to the service.yml
app_bundle.project_tolereances_listener:
class: AppBundle\EventListener\ProjectTolerancesListener
arguments: [@service_container]
and of course I added the following to the listener:
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
but I get the following:
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
Any idea?
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
andpostPersist
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:
Then in
Your\Namespace\Listener
you create the ListenerClassDogListener
: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.and the listener will look like:
According to: How to use Doctrine Entity Listener with Symfony 2.4? it requires DoctrineBundle 1.3+