Ich versuche, ein einfaches Beispiel zu erstellen, um zu lernen, wie eine Zeile aus einer übergeordneten Tabelle gelöscht und die übereinstimmenden Zeilen in der untergeordneten Tabelle mithilfe von Doctrine2 automatisch gelöscht werden.
Hier sind die beiden Entitäten, die ich verwende:
Child.php:
<?php
namespace Acme\CascadeBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="child")
*/
class Child {
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="Father", cascade={"remove"})
*
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="father_id", referencedColumnName="id")
* })
*
* @var father
*/
private $father;
}
Father.php
<?php
namespace Acme\CascadeBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="father")
*/
class Father
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
}
Die Tabellen werden korrekt in der Datenbank erstellt, die Option "Kaskade löschen" wird jedoch nicht erstellt. Was mache ich falsch?
php
doctrine-orm
symfony
cascading-deletes
rfc1484
quelle
quelle
Antworten:
In der Lehre gibt es zwei Arten von Kaskaden:
1) ORM-Ebene - wird
cascade={"remove"}
in der Zuordnung verwendet - Dies ist eine Berechnung, die in UnitOfWork durchgeführt wird und die Datenbankstruktur nicht beeinflusst. Wenn Sie ein Objekt entfernen, durchläuft UnitOfWork alle Objekte in der Zuordnung und entfernt sie.2) Datenbankebene - wird
onDelete="CASCADE"
in der joinColumn der Zuordnung verwendet. Dadurch wird der Fremdschlüsselspalte in der Datenbank On Delete Cascade hinzugefügt:Ich möchte auch darauf hinweisen, dass die Art und Weise, wie Sie Ihre Kaskade haben = {"remove"}, wenn Sie ein untergeordnetes Objekt löschen, diese Kaskade das übergeordnete Objekt entfernt. Ganz klar nicht was du willst.
quelle
onDelete
undcascade = {"remove"}
zum Beispiel, wenn Sie ein Objekt haben, das mit fosUser zusammenhängt. Beide Objekte sollten nicht alleine existieren@ORM\JoinColumn(onDelete="CASCADE")
und die Doktrin die Spaltennamen automatisch verarbeiten lassen können.onDelete="CASCADE"
dies keine Auswirkungen haben wird, da Doctrinecascade={"remove"}
die verwandten Entitäten entfernt, bevor die Stammentität entfernt wird (es muss). Wenn also die Stammentität gelöscht wird, sind keine Fremdbeziehungen mehronDelete="CASCADE"
zum Löschen übrig . Um sicherzugehen, würde ich vorschlagen, dass Sie einfach einen kleinen Testfall erstellen und sich die ausgeführten Abfragen und ihre Ausführungsreihenfolge ansehen.Hier ist ein einfaches Beispiel. Einem Kontakt sind eine bis viele Telefonnummern zugeordnet. Wenn ein Kontakt gelöscht wird, möchte ich, dass auch alle zugehörigen Telefonnummern gelöscht werden. Daher verwende ich ON DELETE CASCADE. Die Eins-zu-Viele / Viele-zu-Eins-Beziehung wird durch den Fremdschlüssel in den Telefonnummern implementiert.
Durch Hinzufügen von "ON DELETE CASCADE" zur Fremdschlüsseleinschränkung werden phone_numbers automatisch gelöscht, wenn der zugehörige Kontakt gelöscht wird.
Wenn nun eine Zeile in der Kontakttabelle gelöscht wird, werden alle zugehörigen phone_numbers-Zeilen automatisch gelöscht.
Um dasselbe in Doctrine zu erreichen und dasselbe Verhalten auf DB-Ebene "ON DELETE CASCADE" zu erhalten, konfigurieren Sie die @ JoinColumn mit der Option onDelete = "CASCADE" .
Wenn Sie es jetzt tun
Sie werden sehen, dass dasselbe SQL generiert wird wie im ersten Raw-SQL-Beispiel
quelle
onDelete="cascade"
wird korrekt in der Entität (auf dem untergeordneten Element) platziert, da dies eine SQL-Kaskadierung ist , die auf dem untergeordneten Element platziert wird . Nur die Doctrine-Kaskadierung (cascade=["remove"]
die hier nicht verwendet wird) wird auf dem Elternteil platziert.