Próbuję zrobić prosty przykład, aby dowiedzieć się, jak usunąć wiersz z tabeli nadrzędnej i automatycznie usunąć pasujące wiersze w tabeli podrzędnej za pomocą Doctrine2.
Oto dwa elementy, których używam:
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;
}
Tabele są poprawnie tworzone w bazie danych, ale opcja On Delete Cascade nie jest tworzona. Co ja robię źle?
php
doctrine-orm
symfony
cascading-deletes
rfc1484
źródło
źródło
Odpowiedzi:
Istnieją dwa rodzaje kaskad w Doctrine:
1) Poziom ORM - używa
cascade={"remove"}
w powiązaniu - jest to obliczenie, które jest wykonywane w UnitOfWork i nie wpływa na strukturę bazy danych. Po usunięciu obiektu UnitOfWork wykona iterację nad wszystkimi obiektami w powiązaniu i usunie je.2) Poziom bazy danych - używa
onDelete="CASCADE"
na złączeniu asocjacji stowarzyszenia - spowoduje to dodanie opcji Usuń kaskadę do kolumny klucza obcego w bazie danych:Chciałbym również zauważyć, że sposób, w jaki masz teraz kaskadę = {"remove"}, jeśli usuniesz obiekt potomny, ta kaskada usunie obiekt macierzysty. Wyraźnie nie to, czego chcesz.
źródło
onDelete
jakcascade = {"remove"}
na przykład, gdy masz jakiś obiekt związany z fosUser. Oba obiekty nie powinny istnieć same@ORM\JoinColumn(onDelete="CASCADE")
i nadal pozwalać doktrynie automatycznie obsługiwać nazwy kolumn.onDelete="CASCADE"
nie będzie to miało żadnego wpływu, ponieważ Doctrine'scascade={"remove"}
usuwa powiązane elementy przed usunięciem elementu głównego (musi). Kiedy jednostka główna zostanie usunięta, nie ma już żadnych relacji zagranicznychonDelete="CASCADE"
do usunięcia. Ale dla pewności zasugerowałbym, aby po prostu utworzyć mały przypadek testowy i spojrzeć na wykonywane zapytania i ich kolejność wykonywania.Oto prosty przykład. Kontakt ma jeden do wielu powiązanych numerów telefonów. Kiedy kontakt zostanie usunięty, chcę, aby wszystkie powiązane z nim numery telefonów również zostały usunięte, więc używam ON DELETE CASCADE. Relacja jeden do wielu / wiele do jednego jest implementowana za pomocą klucza obcego w numerach telefonów.
Po dodaniu „ON DELETE CASCADE” do ograniczenia klucza obcego numery telefonów zostaną automatycznie usunięte po usunięciu powiązanego z nimi kontaktu.
Teraz, gdy wiersz w tabeli kontaktów zostanie usunięty, wszystkie powiązane wiersze o numerach telefonów zostaną automatycznie usunięte.
Aby osiągnąć to samo w Doctrine, aby uzyskać to samo zachowanie na poziomie DB „ON DELETE CASCADE”, skonfiguruj @JoinColumn z opcją onDelete = „CASCADE” .
Jeśli teraz to zrobisz
zobaczysz, że zostanie wygenerowany taki sam SQL, jak w pierwszym przykładzie surowego SQL
źródło
onDelete="cascade"
jest poprawnie umieszczony w bycie (na dziecku), ponieważ tak jest kaskadowanie SQL , które jest umieszczane na potomnym. Jedynie kaskadowanie Doctrine (cascade=["remove"]
które nie jest tutaj używane) jest umieszczane na obiekcie nadrzędnym.