Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preserving changes made to a document with Doctrine's PreUpdate lifecycle event

I have an event subscriber that contains two lifecycle event methods: prePersist and preUpdate. The prePersist one is working as expected - I modify the document, and the changes are reflected later when I retrieve the document. preUpdate is not working as expected, though. Here's basically what it looks like:

/**
 * Also update the foo code when the bar profile is updated.
 * @param LifecycleEventArgs $args
 */
public function preUpdate(LifecycleEventArgs $args)
{
    $document = $args->getDocument();
    if ($document instanceof BarProfile) {
        $document->setFooCode('Salamanders');
    }
}

If I create a document and set its fooCode to 'placeholder' in the perPersist function, then when I retrieve the document later it fooCode is 'placeholder'. If I then update it, and retrieve it again, then I expect its fooCode to be 'Salamanders'. However, it's still 'placeholder'. I've even tried putting error_log() stuff in there and it writes stuff to the logs so I can see that this method is being executed.

Is there a second step I have to do after $document->setFooCode() to make the new value of fooCode stick around?

like image 598
beth Avatar asked Dec 31 '14 00:12

beth


1 Answers

You cannot modify the fields directly in the preUpdate event, you have to modify their primitive values. Changes to associations are not allowed. You would have to do:

$eventArgs->setNewValue('fooCode', 'Salamanders');

You stated "The prePersist one is working as expected - I modify the document, and the changes are reflected later when I retrieve the document."

This leads me to believe that you may not be aware of the difference between persist and update. In Doctrine, a persist occurs when you are creating the object for the first time. An update occurs when you are making changes to an existing object that is already being managed by Doctrine. A lot of people are confused by this, but you do not need to call persist() when you are updating an existing entity, you only need to call flush(). For example:

// inserts a new entity into the database
$document = new Document();
$document->setName('My Document');

$em->persist($document);
$em->flush();

and

// retrieves entity from the database, makes a change, then updates the database
$document = $em->findOneByName('My Document');
$document->setFooCode('Salamanders');

$em->flush();

I encourage you to read the Doctrine documentation like Cerad suggested. Play close attention to the following statements for the preUpdate event:

  • PreUpdate is the most restrictive to use event
  • Changes to associations of the updated entity are never allowed in this event
  • Changes to fields of the passed entities are not recognized by the flush operation anymore, use the computed change-set passed to the event to modify primitive field values
like image 171
Jason Roman Avatar answered Nov 20 '22 12:11

Jason Roman