Doctrine2级联删除与多个父母

时间:2014-09-24 20:05:27

标签: symfony doctrine-orm cascade

我有一系列类,这些类的属性之间有一些稍微复杂的引用。我试图删除一个实体并将删除级联到其子级,但我遇到了外键约束错误。这是我的类结构的一个例子:

<?php
/**
 * @ORM\Entity
 * @ORM\Table(name="student_tests")
 */
class StudentTest implements IEntityAccess {

/**
 *
 * @var int
 * @ORM\Column(type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;
/**
 * @var StudentTestItem[]
 * @ORM\OneToMany(targetEntity="StudentTestItem", mappedBy="studentTest", cascade{"remove","persist"})
 */
protected $studentTestItems;

/**
 * @var Test
 * @ORM\ManyToOne(targetEntity="Test", inversedBy="studentTests")
 */
protected $test;
/**
 * @var \DateTime
 * @ORM\Column(type="datetime", nullable=true)
 */
protected $created;
/**
 * @var User
 * @ORM\ManyToOne(targetEntity="User", inversedBy="studentTests")
 */
protected $student;
}


//...
<?php

/**
 * @ORM\Entity
 * @ORM\Table(name="student_test_items")
 */
class StudentTestItem {

/**
 *
 * @var int
 * @ORM\Column(type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;
/**
 * @var StudentTest
 * @ORM\ManyToOne(targetEntity="StudentTest", inversedBy="studentTestItems")
 */
protected $studentTest;
/**
 * @var User
 * @ORM\ManyToOne(targetEntity="User", inversedBy="studentTestItems", cascade={"persist"})
 */
protected $student;

/**
 * @var TestItem
 * @ORM\ManyToOne(targetEntity="TestItem", inversedBy="studentTestItems", cascade{"persist"})
 */
protected $testItem;
}


//...
/**
 *
 * @ORM\Table(name="tests")
 * @ORM\Entity
 *
 * @ORM\HasLifecycleCallbacks
 */
class Test implements IEntityAccess {
/**
 *
 * @var int
 * @ORM\Column(type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;
/**
 * @var \DateTime
 * @ORM\Column(type="datetime", nullable=true)
 */
protected $startDate;
/**
 * @var StudentTest[]
 * @ORM\OneToMany(targetEntity="StudentTest", mappedBy="test" )
 */
protected $studentTests;

/**
 * @var TestItem[]
 * @ORM\OneToMany(targetEntity="TestItem", mappedBy="test", cascade={"all"})
 */
protected $items;
}



//...
/**
 *
 * @ORM\Table(name="test_items")
 * @ORM\Entity
 */
abstract class TestItem {
/**
 *
 * @var int
 * @ORM\Column(type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;
/**
 * @var Test
 * @ORM\ManyToOne(targetEntity="Test", inversedBy="items")
 */
/**
 * @var StudentTestItem[]
 * @ORM\OneToMany(targetEntity="StudentTestItem", mappedBy="testItem")
 */
protected $studentTestItems;

}



/**
 * This is the primary user object. Used for login and all the other
 * good stuff.
 *
 * @ORM\Table(name="users")
 * @ORM\HasLifecycleCallbacks
class User implements AdvancedUserInterface, \Serializable, IEntityAccess
{
/**
 * @ORM\Column(type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 * @var int
 */
private $id;
/**
 * @var StudentTest[]
 * @ORM\OneToMany(targetEntity="StudentTest", mappedBy="student", cascade={"persist", "remove"})
 */
protected $studentTests;
/**
 * @var StudentTestItem[]
 * @ORM\OneToMany(targetEntity="StudentTestItem", mappedBy="student", cascade={"persist", "remove"})
 */
protected $studentTestItems;
}

假设我要删除学生考试,并将该删除级联到其StudentTestItem子级。为此,我在控制器中运行以下代码。

//... blah blah class definition
/**
* Delete a student test
*
* @return \Symfony\Component\HttpFoundation\Response
* @Route("/studenttest/delete", name="student_test_delete")
*/
public function DeleteStudentTestAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();

    $studentTest = $em->getRepository("MyAcmeBundle:StudentTest")->findOneBy(array("id" => 3));

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

    return $this->redirect($this->generateUrl('student_delete_success'));
}

当我尝试运行该代码时,收到以下错误消息:

An exception occurred while executing 'DELETE FROM student_tests WHERE id = ?' with params [3]:
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`my_acme_bundle/student_test_items`, CONSTRAINT `FK_71FA2A7F36BB1A1` FOREIGN KEY (`student_test_id`) REFERENCES `student_tests` (`id`))
500 Internal Server Error - DBALException

现在,如果我从类中删除对studentTestItems的所有引用,即我从TestItem和User类中注释掉$ studentTestItems,它会删除没有该问题的罚款。为什么会这样? Doctrine是否通过关联或其他东西跟踪父引用?

1 个答案:

答案 0 :(得分:3)

您似乎忘了将ON DELETE CASCADE添加到外键约束中。尝试在class StudentTestItem中更改以下关联:

/**
 * @var StudentTest
 * @ORM\ManyToOne(targetEntity="StudentTest", inversedBy="studentTestItems")
 */
protected $studentTest;

对此:

/**
 * @var StudentTest
 * @ORM\ManyToOne(targetEntity="StudentTest", inversedBy="studentTestItems")
 * @ORM\JoinColumn(name="student_test_id", referencedColumnName="id", onDelete="CASCADE")
 */
protected $studentTest;