【问题标题】:Delete all relation when Deleting a row in laravel在laravel中删除一行时删除所有关系
【发布时间】:2020-03-16 06:15:04
【问题描述】:

我有帖子、评论和通知表

每个帖子都有很多 cmets

每条评论都有很多通知

每个帖子都有很多通知

class Post extends Model
{

    public function notifications() {
        return $this->morphOne(Notification::class, 'to');
    }

    public function comments() {
        return $this->hasMany(Comment::class, 'post_id');
    }

    public static function boot() {
        parent::boot();

        static::deleting(function($post) {
            $post->comments()->delete();
            $post->notifications()->delete();
        });
    } 
}
class Comment extends Model
{
    public function notifications() {
        return $this->morphOne(Notification::class, 'to');
    }

    public static function boot() {
        parent::boot();

        static::deleting(function($comment) {
            $comment->notifications()->delete();
        });
    }
}

当我删除帖子时,我应该删除通知和 cmets, 但问题是当我删除 cmets 时,通知不会随之删除, 当我直接删除评论时它们被删除,但我删除帖子时需要删除cmets的通知!

【问题讨论】:

  • 你能显示你如何删除帖子的代码吗?
  • Laravel 不会实例化它删除的相关模型,这就是为什么直接删除评论会删除通知,而删除帖子删除 cmets 时不会。您必须在删除帖子时实例化 cmets 才能使其正常工作

标签: php laravel eloquent eloquent-relationship


【解决方案1】:

Laravel 不会实例化它删除的相关模型,这就是为什么当你直接删除评论时会删除通知,而不是通过删除帖子删除 cmets 时。您必须在删除帖子时实例化 cmets 才能使其正常工作。

class Post extends Model {
    
    public function notifications() {
        return $this->morphOne(Notification::class, 'to');
    }
    
    public function comments() {
        return $this->hasMany(Comment::class, 'post_id');
    }
    
    public static function boot() {
        parent::boot();
    
        static::deleting(function($post) {
            // here you could instantiate each related Comment
            // in this way the boot function in the Comment model will be called
            $post->comments->each(function($comment) {
                // and then the static::deleting method when you delete each one
                $comment->delete();
            });
            $post->notifications()->delete();
        });
    } 
}

为了记录,我添加了我们在 cmets 中讨论的内容,因为它可以为遇到相同问题的其他人提供服务,而在 cmets 中它可能会被忽视。归功于 OP @Mahmoud Ben Jabir。

但是如果帖子有 100 个 cmets 它将执行 100 个查询来删除它们!我会弄清楚如何用最少的查询删除...

我已经在 cmets 上设置了 onDelete,但是通知是多态的,所以它对它们不起作用...

我将使用的解决方案是:
1- 获取与帖子相关的评论 ID。
2- 从通知中删除,其中类型为评论和(id)中的 id。
3- 删除与帖子相关的评论。
4-删除与帖子相关的通知
5- 删除帖子。

public static function boot() {
    parent::boot();
    static::deleting(function($post) {
        // 1- Get Ids of Comments that are related to the Post. 
        $ids = $post->comments()->pluck('id'); 
        // 2- Delete from Notifications where type IS Comment AND id in (ids). 
        Notification::where('entity_type', 'App\Comment')->whereIn('entity_id', $ids)->delete(); 
        // 3- Delete Comments related to the Post. 
        $post->comments()->delete();
        // 4- Delete The Notifications Related to the Post 
        $post->notifications()->delete();
    });
    // 5- Delete The Post.
}

【讨论】:

  • 好的,这会起作用,但是如果帖子有 100 个 cmets,它将执行 100 个查询以删除它们!我会弄清楚如何用最少的查询删除,谢谢
  • @MahmoudBenJabir 是的,你是对的。我认为更有效的方法是在数据库级别使用->onDelete('cascade'),但仅适用于关系数据库并在数据库级别配置外键
  • 我已经在 cmets 上有 onDelete,但是通知是多态的,所以它对它们不起作用,我想出了一种方法来获取 cmets 的 ID,然后手动删除通知而不是依赖 Eloquent关系...谢谢大家的讨论
  • 我将使用的解决方案是: 1- 获取与帖子相关的评论 ID。 2- 从通知中删除,其中类型是评论和(ids)中的 id。 3- 删除与成本相关的评论。 4-删除与帖子相关的通知 5-删除帖子。有什么建议吗?
  • 是的,我用的是同一个登录名,而且成功了,我用的是第二个,只是用这种方式删除了cmets,$post->cmets()->deleted();
【解决方案2】:

请使用(假设 post 和 cmets 之间的关系)

$table->foreign('post_id')
      ->references('id')->on('posts')
      ->onDelete('cascade');

在您的迁移文件中建立外部关系。所以当你删除相关帖子时,它的评论也会被删除。

【讨论】:

  • 我说的是评论通知!
  • 这也可以在通知和评论的关系中完成。
【解决方案3】:

链接不起作用,因为模型没有初始化。
最佳解决方案是循环并删除单个 cmets

static::deleting(function($post) {
    foreach ($post->comments() as $comment){
        $comment->delete();
    }
});

【讨论】:

    【解决方案4】:
    static::deleting(function($comment) {
        $ids = $comment->notifications()->lists('id')->all();
        Notification::destroy($ids);
    });
    

    【讨论】:

      猜你喜欢
      • 2018-11-03
      • 2016-05-01
      • 1970-01-01
      • 2018-05-19
      • 1970-01-01
      • 2015-05-15
      • 2020-08-02
      • 1970-01-01
      • 2016-01-02
      相关资源
      最近更新 更多