Axel Agarrat
Axel Agarrat

Reputation: 589

Remove element from ArrayCollection on OneToMany wont delete it on persist()?

In a Zend Framework 2 project, we got two Doctrine 2 entities and we would like to remove an element from a collection allready saved in the database...

So we have a first entity named FormGroupConstraint :

/**
 * FormGroupConstraint
 *
 * @ORM\Table(name="form_group_constraint")
 * @ORM\Entity(repositoryClass="Application\Dao\FormGroupConstraintDao")
 */
class FormGroupConstraint {

    /**
     * @var integer 
     * 
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
     protected $id;

    /**
     * @param \Doctrine\Common\Collections\ArrayCollection
     * @ORM\OneToMany(targetEntity="Application\Entity\FormQuestionConstraint", mappedBy="groupConstraint", fetch="EAGER", cascade={"persist", "merge", "refresh", "remove"})
     */
     protected $constraints;

     public function __construct() 
          $this->constraints = new \Doctrine\Common\Collections\ArrayCollection();
     }

     /**
     * @param \Doctrine\Common\Collections\ArrayCollection $constraints
     */
     public function addConstraints($constraints) {
        foreach ($constraints as $constraint) {
            $this->constraints->add($constraint);
        }
        return $this->constraints;
    }
    /**
     * @param \Doctrine\Common\Collections\ArrayCollection $constraints
     */
     public function removeConstraints($constraintsToRemove) {
            foreach ($constraintsToRemove as $key => $constraintToRemove) {
                $this->constraints->removeElement($constraintToRemove);
            }
            return $this->constraints;
     }
}

And the sub entity named FormQuestionConstraint :

/**
 * FormQuestionConstraint
 *
 * @ORM\Table(name="form_question_constraint")
 * @ORM\Entity(repositoryClass="Application\Dao\FormQuestionConstraintDao")
 */
class FormQuestionConstraint
{
    /**
    * @var integer
    *
    * @ORM\Column(name="id", type="integer", nullable=false)
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="IDENTITY")
    */
    protected $id;

    /**
    * @var \Application\Entity\FormGroupConstraint
    *
    * @ORM\ManyToOne(targetEntity="Application\Entity\FormGroupConstraint", cascade=   {"persist", "merge", "refresh", "remove"})
    * @ORM\JoinColumns({
    *   @ORM\JoinColumn(name="form_group_constraint_id", referencedColumnName="id")
    * })
    */
    protected $groupConstraint;
}

So if we try to create, persist, flush a FormGroupConstraint entity, no problem, but when we want to remove an element of $constraints ArrayCollection, nothing happens...

We are using doctrine-orm-module for zend 2 installed with composer.phar in dev-master...

Here is an example of what we are trying to do :

$constraint = $this->findConstraintByGroup(1);

$formGroupConstraint = $this->_em->findOneById(1);

$formGroupConstraint->getConstraints()->removeElement($constraint);
$this->_em->persist($formGroupConstraint);
$this->_em->flush();

No error, but no delete or remove... And if we var_dump() the getConstraints() before persist(), actually the element is still in the ArrayCollection...

Could anyone explain us how we could do that or why the element is not removed ?

Upvotes: 12

Views: 14022

Answers (3)

likeitlikeit
likeitlikeit

Reputation: 5638

You could add orphanRemoval=true on the OneToMany side of the relation, for instance like this:

@ORM\OneToMany(
    targetEntity="Application\Entity\FormQuestionConstraint",
    mappedBy="groupConstraint",
    cascade={"all"},
    orphanRemoval=true
)

The reason for this behaviour is that the entity is removed from the ArrayCollection, but the collection's contents are only determined by the child entity's foreign key pointing to the parent entity.

When doctrine looks up the parent entity's children for the next time, it's still there and will be shown in the next request again, when the ArrayCollection is fetched from the database again.

If orphanRemoval is set to true, such child entities will be removed upon persist().

Upvotes: 7

olegkhuss
olegkhuss

Reputation: 3842

Maybe a bit late but try adding orphanRemoval=true to the inverse side (OneToMany) of relationship

@ORM\OneToMany(
    targetEntity="Application\Entity\FormQuestionConstraint",
    mappedBy="groupConstraint",
    cascade={"persist", "remove"},
    orphanRemoval=true
)

Upvotes: 33

dylan oliver
dylan oliver

Reputation: 1284

Because the reference is held on FormQuestionConstraint you need to do:

$this->_em->remove($constraint);
$this->_em->flush();

Upvotes: 3

Related Questions