Doctrine: Exception in One-To-Many cascading: Integrity constraint violation 1451

pdresselhaus :

I am trying to build a very basic CMS using Symfony and Doctrine. I have entities emulating my sites' structure like so:

Entity: Page

/**
 * @ORM\Entity(repositoryClass="App\Repository\ContentTree\PageRepository")
 */
class Page extends SortableBase
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     * @ORM\OrderBy({"sort_order" = "ASC"})
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="Website", inversedBy="pages", cascade={"all"}, fetch="EAGER")
     */
    private $website;

    /**
     * Owning side of relation
     * @ORM\OneToMany(targetEntity="Section", mappedBy="page", fetch="EAGER")
     */
    private $sections;


    public function __construct()
    {
    ...

Entity: Section

/**
 * @ORM\Entity(repositoryClass="App\Repository\ContentTree\SectionRepository")
 */
class Section extends SortableBase
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="Page", inversedBy="sections", cascade={"all"}, fetch="EAGER")
     */
    private $page;

    /**
     * Owning side of relation
     * @ORM\OneToMany(targetEntity="Entry", mappedBy="section", fetch="EAGER")
     */
    private $entries;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\SectionTemplating\SectionType", fetch="EAGER")
     */
    private $sectionType;


    public function __construct()
    {

Entity: Entry

/**
 * @ORM\Entity(repositoryClass="App\Repository\ContentTree\EntryRepository")
 */
class Entry extends SortableBase
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="Section", inversedBy="entries", cascade={"all"}, fetch="EAGER")
     */
    private $section;

    /**
     * Owning side of relation
     * @ORM\OneToMany(targetEntity="App\Entity\ContentTypes\Content", mappedBy="entry", fetch="EAGER")
     */
    private $contents;


    public function __construct()
    {
    ...

So in the end a Page can have Sections which can have Entries and so forth. Now, from what I gathered from the docs I was under the assumption that with how I setup the cascades I could just go and use the EntityManager to remove an instance of any Entity (lets say Section) and it would automatically delete that instance as well as all contained Entries.

However, when I do something like:

$section = $this->getSectionByID($sectionid);

$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($section);
$entityManager->flush();

as soon as the Section has any Entries, I get:

An exception occurred while executing 'DELETE FROM section WHERE id = ?' with params [10]:

SQLSTATE[23000]: Integrity constraint violation: 
1451 Cannot delete or update a parent row: 
a foreign key constraint fails (`webdata`.`entry`, CONSTRAINT `FK_2B219D70D823E37A` 
FOREIGN KEY (`section_id`) REFERENCES `section` (`id`))

I know what it it means but I just cannot figure out what I should do different here in order to force the EntityManager to traverse down my entity graph and delete everything from bottom to top.

pdresselhaus :

Turns out that in order for Doctrine to cascade a remove down the entity-relation-graph one would simply annotate the owning side like so:

/**
 * Owning side of relation
 * @ORM\OneToMany(targetEntity="Page", mappedBy="website", cascade={"all"}, fetch="EAGER")
 */
private $pages;

This, however, really just tells the ORM what you want to happen during an e.g. remove. This will not suffice to model what will happen during the actual call to your database. For this, one will have to add an additional @ORM\JoinColumn(onDelete="CASCADE") to the inverse side, like so:

/**
 * @ORM\ManyToOne(targetEntity="Website", inversedBy="pages", fetch="EAGER")
 * @ORM\JoinColumn(onDelete="CASCADE")
 */
private $website;

With this everything works as intended. I am also finally able to manually remove entries via phpMyAdmin which also gave me errors before.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=293523&siteId=1