5

I have Posts, Comments and notifications Table

Every Post hasMany comments

every comment hasMany Notifications

every Post hasMany Notifications

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();
        });
    }
}

When I delete a post I should Delete The notifications and the comments as well, But the problem is When I delete the comments, The Notifications aren't deleted with it, They are deleted When I delete The Comment Directly but I need to delete the notifications of the comments When I delete the post !

2
  • Can you show the code on how you delete the post? Commented Nov 20, 2019 at 14:12
  • Laravel does not instantiate the related models that it deletes, which is why notifications are deleted when you directly delete a comment, but not when comments are deleted by deleting a post. you would have to instantiate the comments when deleting a post to make it work Commented Nov 20, 2019 at 14:13

4 Answers 4

4

Laravel does not instantiate the related models that it deletes, which is why notifications are deleted when you directly delete a comment, but not when comments are deleted by deleting a post. You would have to instantiate the comments when deleting a post to make it work.

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();
        });
    } 
}

Just for the records, I add what we discuss in the comments since it can serve others who encounter the same issue, and in the comments it can go unnoticed. Credit is for OP @Mahmoud Ben Jabir.

But if the post has 100 comments It will execute 100 query to delete them ! I will Figure out how to delete with minimum queries...

I already have onDelete on comments, but the notifications are polymorphic so it won't work on them...

The solution I will use is:
1- Get Ids of Comments that are related to the Post.
2- Delete from Notifications where type IS Comment AND id in (ids).
3- Delete Comments related to the Post.
4- Delete The Notifications Related to the Post
5- Delete The Post.

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.
}
Sign up to request clarification or add additional context in comments.

7 Comments

Ok This Will Work, But if the post has 100 comments It will execute 100 query to delete them ! I will Figure out how to delete with minimum queries, Thanks
@MahmoudBenJabir Yes, you are right. I think the more eficient way if to do it on DB level, with ->onDelete('cascade'), but only will work with relationals databases and configuring foreign keys on DB level
I already have onDelete on comments, but the notifications are polymorphic so it won't work on them, I figured out a way to get the Ids of comments then delete the notifications Manually instead of relying on Eloquent relationships ... thanks man for the discussion
The solution I will use is: 1- Get Ids of Comments that are related to the Post. 2- Delete from Notifications where type IS Comment AND id in (ids). 3- Delete Comments related to the Cost. 4- Delete The Notifications Related to the Post 5- Delete The Post. Any suggestions about it ?
Yes it's the same login I used And it worked, I used the second one, and just deleted comments in this way, $post->comments()->deleted();
|
1
static::deleting(function($comment) {
    $ids = $comment->notifications()->lists('id')->all();
    Notification::destroy($ids);
});

Comments

1

Chaining will not work, because the models aren't initialised.
Best solution is to loop and delete the individual comments

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

Comments

0

Please use (assuming relation between post and comments)

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

to make a foreign relation in your migration file. So then when you delete related post it's comment will be deleted also.

2 Comments

I'm talking about notifications of the comment !
This could also be done in relation of notification and comment.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.