[英]Automatically deleting NESTED related rows in Laravel 5.4 (Eloquent ORM)
假设我有一本书。 本书有各章,而本书中的各章都有子章。
所以我有三种模型:
图书>章>章节
当我删除本书时($ book-> delete();),我也想删除本书的相关章节以及本书所有章节的相关子章节。
在这里( 自动删除Laravel(Eloquent ORM)中的相关行 )我发现了关于Eloquent事件的信息。 每当删除一本书时,在此之前,该章都会被删除,因为我们会钩住:
class Book extends Eloquent
{
public function chapters()
{
return $this->has_many('Chapter');
}
protected static function boot() {
parent::boot();
static::deleting(function($book) {
$book->chapters()->delete();
});
}
}
所以我想,我只需要在我的章节模型中实现相同的代码,只需将“ Book”与“ Chapter”交换,并将“ Chapter”与“ Subchapter”交换:
class Chapter extends Eloquent
{
public function subChapters()
{
return $this->has_many('SubChapter');
}
protected static function boot() {
parent::boot();
static::deleting(function($chapter) {
$chapter->subChapters()->delete();
});
}
}
当我删除章节时,这可以正常工作。 所有子章节也将被删除。
当我删除这本书时,它可以很好地适用于各章。 所有章节也将被删除。
但是,只有在删除本书时,它才会删除章节。 它不会删除已删除章节的相关子章节。
有谁能够帮助我?
这是因为$book->chapters()
只会返回Builder
一个实例。 当你调用delete()
的制造商将只是简单地运行删除这些模型所需的查询,而不是新起来,然后将其删除,这将意味着deleting
的事件Chapter
将永远不会被解雇。
要解决此问题,您可以执行以下操作:
protected static function boot() {
parent::boot();
static::deleting(function($book) {
$book->chapters->each(function ($chapter) {
$chapter->delete();
});
});
}
希望这可以帮助!
正确的方法是使用onDelete('cascade')
。 在表迁移chapters
中:
$table->foreign('book_id')
->references('id')
->on('books')
->onDelete('cascade');
在子subchapters
迁移中:
$table->foreign('chapter_id')
->references('id')
->on('chapters')
->onDelete('cascade');
在这种情况下,您无需编写任何代码,所有章节和子章节将自动删除。
这是因为当您同时删除多个对象时,它不会触发每个模型的启动删除功能,因此您应该遍历对象并逐个删除它们:
class Book extends Eloquent
{
public function chapters()
{
return $this->has_many(Chapter::class);
}
protected static function boot() {
parent::boot();
static::deleting(function($book) {
foreach($book->chapters as $chapter){
$chapter->delete();
}
});
}
}
/********************************/
class Chapter extends Eloquent
{
public function subChapters()
{
return $this->has_many(SubChapter::class);
}
protected static function boot() {
parent::boot();
static::deleting(function($chapter) {
foreach($chapter->subChapters as $subChapter){
$subChapter->delete();
}
});
}
}
但是,我的建议是在表之间设置级联外键关系,以便DBMS将自动删除相关行,下面的示例代码向您展示了如何在迁移文件中执行此操作:
Schema::create('chapters', function (Blueprint $table) {
$table->increments('id');
$table->integer('book_id')->unsigned();
$table->string('title');
$table->timestamps();
$table->foreign('book_id')
->references('id')
->on('books')
->onDelete('cascade')
->onUpdate('cascade');
});
对子章节执行相同的操作。 希望能帮助到你...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.