Question

I have a recursive entity containing parent/children item

  namespace Vendor\StructureBundle\Entity;

use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Events;
use Gedmo\Mapping\Annotation as Gedmo;
/**
 * Vendor\StructureBundle\Entity\Structure
 * @Gedmo\Tree(type="nested")
 *
 * @ORM\Table(name="lowbi_structure")
 * @ORM\Entity(repositoryClass="Gedmo\Tree\Entity\Repository\NestedTreeRepository")
 * @ORM\HasLifecycleCallbacks()
 * @CustomAssert\ganttDate
 */
         class Structure {

              /**
               * @var integer $id
               *
               * @ORM\Column(name="id", type="integer")
               * @ORM\Id
               * @ORM\GeneratedValue(strategy="AUTO")
               */
              private $id;
    ...

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

              /**
               * @Gedmo\TreeParent
               * @ORM\ManyToOne(targetEntity="Structure", inversedBy="children",cascade={"persist"})
               * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
               */
              private $parent;
              /*
               * @ORM\OneToMany(targetEntity="Structure", mappedBy="parent",cascade={"persist","remove"})
               * @ORM\OrderBy({"lft" = "ASC"})
               */
              private $children;
    ...

          }

and i want to update the "parent" when i persit this entity.

/**
* Set prePersist
* 
* @ORM\PrePersist()
* @ORM\PreUpdate()
* 
*/
public function prePersist()
{
    $this->getParent()->setTitle('Foo');
}

The probleme is that my current entity is persisted but the parent entity is not. The title is not saved. How can i save the parent's properties?

PS : I simplified the code. In real world, i need to update parent start dates/end dates to fit the children (project management tree)

Was it helpful?

Solution

What you're trying to do here is not possible with a Lifecycle callback (i.e. @PrePersist) if you save only the child afterwards.

Doctrine only tracks and saves changes to the owning side of a relation.

When a bidirectional assocation is updated, Doctrine only checks on one of both sides for these changes. This is called the owning side of the association.

Therefore you can't persist an update of the parent from the child by persisting the child only.

You can find more information about the concepts of the inverse and owning side in this answer and in the documentation chapter Working with Associations.

To solve this issue ... you can either persist the parent instead of the child ... or (instead of using the lifecycle callback @PrePersist) create an event listener that will automatically persist the parent. This is a better practice in general because it keeps application logic out of your model.

The documentation chapter How to Register Event Listeners and Subscribers provides all the necessary information to get you started.

OTHER TIPS

I don't know why, but if i return $this in the prePersist function, IT WORKS.

**
* Set prePersist
* 
* @ORM\PrePersist()
* @ORM\PreUpdate()
* 
*/
public function prePersist()
{
    //$this->getParent()->setTitle('Foo');
    return $this->getParent()->setTitle('Foo'); //solved this problem!!!!
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top