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