Home > OS >  call "deleting" function with cascadeOnDelete()
call "deleting" function with cascadeOnDelete()

Time:09-05

I am developing an app in which you can create events and add posts to them. I have two Tables called events and posts. The events table has a preview_image column. The posts table has a picture column and a foreignId event_id.

Schema::create('events', function (Blueprint $table) {
    $table->id('id');
    // ...
    $table->string('preview_image')->nullable();
    // ...
});
Schema::create('posts', function (Blueprint $table) {
    $table->id('id');
    // ...
    $table->string('picture');
    $table->foreignId('event_id')->constrained()->cascadeOnDelete();
    // ...
});

An example for an entry in both colums looks like this

Post

picture: "posts/2Ddh4wiTrBGBWQkRhQbTUTFGdVCFoW3KzvIhpfKW.png"

Event

preview_image: "events/lOzjzjSZul4tGULxzxfIxzfJGBlohe9np6NLazjA.jpg"

In my Event model I am overwriting the boot method to create a deleting function to delete the preview_image

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

    static::deleting(function($event) {
        $picture = $event->preview_image;
        if ($picture) {
            $picturePath = storage_path('app/public/' . $picture);
            if (file_exists($picturePath)) {
                unlink($picturePath);
            }
        }
    });
}

When I delete an Event all relating posts and the preview_image gets deleted. Now I want the picture of every post to be deleted when the Post is deleted. So I did the same thing to my Post model.

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

    static::deleting(function ($post) {
        $picture = $post->picture;
        if ($picture) {
            $picturePath = storage_path('app/public/' . $picture);
            if (file_exists($picturePath)) {
                unlink($picturePath);
            }
        }
    });
}

My file structure:

app
 public
   events
      event1.png
   posts
      post1.png

This is the function I am calling to delete the Event

public function deleteEvent($id)
{
    $event = Event::findOrFail($id);
    $event->delete();
    return response()->json($event);
}

For some reason the picture of the post does not get deleted.

Does the deleting function not get called if the posts are removed by cascadeOnDelete()? If so how can I call the deleting function while deleting each post. Or is there another method to delete relating files with cascadeOnDelete().

laravel version: v9.24.0

CodePudding user response:

A cascading delete happens at the database level. There are no Eloquent events fired.

If you need Eloquent events to fire on the deleted child records, you'll need to ditch cascadeOnDelete, and implement the deletion cascade yourself via a deleted event on the parent model.

CodePudding user response:

cascading delete does not execute the deleting function in my Post model. Like ceejayoz said:

A cascading delete happens at the database level. There are no Eloquent events fired.

I solved this problem by calling the delete function of each post before deleting the event.

public function deleteEvent($id)
{
    $event = Event::findOrFail($id);
    $posts = $event->posts;
    foreach ($posts as $post){
        $post->delete();
    }
    $event->delete();
    return response()->json($event);
}

now cascadeOnDelete is unnecessary and I can remove it

  • Related