Symfony3:在3级别的删除级联上不起作用(2个实体)

时间:2016-09-28 14:06:39

标签: mysql doctrine-orm associations symfony cascading-deletes

我有这个结构:

Root Level
-- Level 1         id : 1100    --> trying to delete this level
---- Level 1.1     id : 1101
------ product 1
------ product 2

我想删除级别1,级联删除级别1.1及其2个子级。

当我这样做时,我违反了完整性约束:

$em->remove($level);
$em->flush();

$level代表等级1

  

使用params [1100]

执行DELETE FROM level WHERE id = ?时发生异常      

无法删除或更新父行:外键约束失败(mydb.product,CONSTRAINT my_constraint FOREIGN KEY(Level_ID)REFERENCES level(id))

此错误似乎出现在"产品"表

我的实体:

class Level
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue
     */
    private $id;

    /**
     * @Gedmo\TreeParent
     * @ORM\ManyToOne(targetEntity="Level", inversedBy="children")
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
     */
    private $parent;

    /**
     * @ORM\OneToMany(targetEntity="Level", mappedBy="parent")
     * @ORM\OrderBy({"lft" = "ASC"})
     */
    private $children;

    /**
     * @ORM\OneToMany(targetEntity="Product", mappedBy="level", cascade={"persist", "remove"})
     * @ORM\OrderBy({"order" = "ASC"})
     * @Assert\Valid
     */
    private $products;
}

此实体是根据Tree extension for Doctrine2

构建的

A Level可以拥有父级(同一实体)。

A Level可以有一个或多个产品。

class Product
{
    /**
     * @ORM\Column(name="Product_Code", type="string", length=20)
     * @ORM\Id
     */
    private $code;

    /**
     * @ORM\Column(name="Level_ID", type="integer")
     * @ORM\Id
     */
    private $levelId;

    /**
     * @ORM\ManyToOne(targetEntity="Level", inversedBy="products")
     * @ORM\JoinColumn(name="Level_ID", referencedColumnName="id")
     */
    private $level;

}

我不太清楚问题出在哪里。通常,应首先删除产品,然后删除1.1级和1级。

1级没有产品但是,它可能会尝试删除level_id = 1100(而不是1101)的产品?

如果没有产品,删除效果很好。当我删除具有子级别的级别时,会正确删除所有级别。

cascade={"persist", "remove"}似乎不适用于我的产品系列(在Level实体中)。

这很奇怪,因为我在数组集合等中使用了很多实体和关系,之前我没有遇到过这个错误。

感谢您的帮助。

修改

我找到了一个解决方案,但我认为这不是正确的方法。我必须在控制器中手动执行级联删除:

/* browse children levels */
foreach ($level->getChildren() as $child) {

    /* browse the products within the child level */
    foreach ($child->getProducts() as $product) {
        $em->remove($product);    -- delete product
    }
}

$em->remove($level);     -- delete the level (delete also children levels)
$em->flush();           -- update database

0 个答案:

没有答案