Saya mencoba membuat contoh sederhana untuk mempelajari cara menghapus baris dari tabel induk dan secara otomatis menghapus baris yang cocok di tabel anak menggunakan Doctrine2.
Berikut adalah dua entitas yang saya gunakan:
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;
}
Tabel dibuat dengan benar pada database, tetapi opsi On Delete Cascade tidak dibuat. Apa yang saya lakukan salah?
php
doctrine-orm
symfony
cascading-deletes
rfc1484
sumber
sumber
Jawaban:
Ada dua jenis kaskade dalam Doktrin:
1) Level ORM - gunakan
cascade={"remove"}
dalam asosiasi - ini adalah perhitungan yang dilakukan di UnitOfWork dan tidak mempengaruhi struktur database. Saat Anda menghapus objek, UnitOfWork akan beralih ke semua objek dalam asosiasi dan menghapusnya.2) Level database - digunakan
onDelete="CASCADE"
pada joinColumn asosiasi - ini akan menambahkan On Delete Cascade ke kolom kunci asing di database:Saya juga ingin menunjukkan bahwa cara Anda memiliki kaskade Anda = {"hapus"} sekarang, jika Anda menghapus objek Anak, kaskade ini akan menghapus objek Induk. Jelas bukan yang Anda inginkan.
sumber
onDelete
dan jugacascade = {"remove"}
misalnya ketika Anda memiliki beberapa objek yang terkait dengan fosUser. Kedua objek tidak boleh ada sendirian@ORM\JoinColumn(onDelete="CASCADE")
dan membiarkan doktrin menangani nama kolom secara otomatis.onDelete="CASCADE"
itu tidak akan memengaruhi apa pun karena Doctrinecascade={"remove"}
menghapus entitas terkait sebelum menghapus entitas root (harus). Jadi ketika entitas root dihapus, tidak ada hubungan luar negeri yang tersisa untukonDelete="CASCADE"
dihapus. Tetapi untuk memastikan saya menyarankan Anda cukup membuat test case kecil dan melihat pertanyaan yang dieksekusi dan urutan eksekusi mereka.Ini adalah contoh sederhana. Kontak memiliki satu hingga banyak nomor telepon terkait. Ketika kontak dihapus, saya ingin semua nomor telepon yang terkait juga dihapus, jadi saya menggunakan ON DELETE CASCADE. Hubungan satu-ke-banyak / banyak-ke-satu diimplementasikan dengan kunci asing di nomor telepon.
Dengan menambahkan "ON DELETE CASCADE" ke batasan kunci asing, nomor telepon akan secara otomatis dihapus ketika kontak mereka yang terkait dihapus.
Sekarang ketika baris dalam tabel kontak dihapus, semua baris nomor telepon yang terkait secara otomatis akan dihapus.
Untuk mencapai hal yang sama di Doctrine, untuk mendapatkan behavoir DB-level "ON DELETE CASCADE" yang sama, Anda mengkonfigurasi @JoinColumn dengan opsi onDelete = "CASCADE" .
Jika sekarang Anda lakukan
Anda akan melihat bahwa SQL yang sama akan dihasilkan seperti pada contoh, baku-SQL
sumber
onDelete="cascade"
ditempatkan dengan benar dalam entitas (pada anak) karena itu adalah cascading SQL , yang ditempatkan pada anak. Hanya Cascading Doctrine (cascade=["remove"]
, yang tidak digunakan di sini) ditempatkan pada orang tua.