我有一系列类,这些类的属性之间有一些稍微复杂的引用。我试图删除一个实体并将删除级联到其子级,但我遇到了外键约束错误。这是我的类结构的一个例子:
<?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是否通过关联或其他东西跟踪父引用?
答案 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;