从OneToMany上的ArrayCollection中删除元素不会在persist()上删除它?

Axe*_*rat 11 doctrine-orm

在Zend Framework 2项目中,我们有两个Doctrine 2实体,我们希望从已经保存在数据库中的集合中删除一个元素...

所以我们有一个名为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;
     }
}
Run Code Online (Sandbox Code Playgroud)

并且名为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;
}
Run Code Online (Sandbox Code Playgroud)

因此,如果我们尝试创建,持久化,刷新FormGroupConstraint实体,没问题,但是当我们想要删除$ constraints ArrayCollection的元素时,没有任何反应......

我们使用doctrine-orm-module为zend 2安装了dever master中的composer.phar ...

以下是我们尝试做的一个示例:

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

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

$formGroupConstraint->getConstraints()->removeElement($constraint);
$this->_em->persist($formGroupConstraint);
$this->_em->flush();
Run Code Online (Sandbox Code Playgroud)

没有错误,但没有删除或删除...如果我们在persist()之前var_dump()getConstraints(),实际上该元素仍然在ArrayCollection中......

任何人都可以解释我们如何做到这一点或为什么元素不被删除?

小智 29

也许有点晚,但尝试添加orphanRemoval=true到反面(OneToMany)的关系

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

  • 小心,ManyToOne没有属性orphanRemoval,这必须在OneToMany方面 (7认同)

lik*_*eit 7

您可以orphanRemoval=true在关系的一侧添加OneToMany,例如这样:

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

出现此行为的原因是该实体已从 ArrayCollection 中删除,但集合的内容仅由指向父实体的子实体的外键确定。

当原则下次查找父实体的子实体时,它仍然存在,并且当再次从数据库中获取 ArrayCollection 时,将再次显示在下一个请求中。

如果orphanRemoval设置为true,则此类子实体将被删除persist()


dyl*_*ver 3

因为参考资料是关于FormQuestionConstraint你需要做的:

$this->_em->remove($constraint);
$this->_em->flush();
Run Code Online (Sandbox Code Playgroud)

  • 来自[doctrine关联文档](http://docs.doctrine-project.org/en/latest/reference/unitofwork-associations.html):“Doctrine将*仅*检查关联的拥有方是否有更改。” 因为引用保存在“FormQuestionConstraint”上,所以您需要按照我的回答中的指示将其删除。 (2认同)