繁体   English   中英

自动删除Laravel 5.4(Eloquent ORM)中与NESTED相关的行

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM