There are 2 Eloquent models in my project: App\StoredFile
and App\StoredImageSize
.
The StoredFile
model is responsible for keeping uploaded files info. If the uploaded file would be an image, then 2 thumbnails will be stored in storage and their attributes in DB (StoredImageSize
model).
Relationships are as below:
StoredFile.php:
public function sizes()
{
return $this->hasMany('App\StoredImageSize');
}
StoredImageSize.php:
public function originalImage()
{
return $this->belongTo('App\StoredFile');
}
StoredImageSize
has an observer class (StoredImageSizeObserver
) which has been registered through a ServiceProvider and works well.
The problem is that I want to delete the actual file from storage (in my case hard disk) when deleting the subsequent row from database.
StoredImageSizeObserver.php:
public function deleting(StoredImageSize $file)
{
Storage::delete($file->server_url);
}
The logic is something like this:
$file = StoredFile::find(1);
$file->sizes()->delete(); // it does delete all related rows from 'StoredImageSize' but not files from storage
$file->delete()
actually it never hits deleting
method from StoredImageSizeObserver
class as Laravel documentation says:
When executing a mass delete statement via Eloquent, the deleting and deleted model events will not be fired for the deleted models. This is because the models are never actually retrieved when executing the delete statement.
So, How should I tackle this situation? Any solution or recommendation would be appreciated.
Laravel Soft Cascade is a package that makes it easy to perform soft cascade deletes and restores on related models using soft deleting.
Step 1: Create Controller UserController by executing this command. Step 2: We can delete records in two ways. Second Method: The second way is to delete using the Laravel delete Function and User Model (Easy one). ->name( 'users.
In the StoredFile
model add the following method, you have two choices :
the first :
protected static function boot() {
parent::boot();
static::deleting(function(StoredFile $fileToDelete) {
foreach ($fileToDelete->sizes as $size)
{
$size->delete();
}
$fileToDelete->delete()
});
}
The second :
protected static function boot() {
parent::boot();
static::deleting(function(StoredFile $fileToDelete) {
$size_ids = $fileToDelete->sizes()->lists('id');
StoredImageSize::whereIn($size_ids)->delete();
$fileToDelete->delete()
});
}
Or create an observer for the StoredFile
model not for the StoredImageSize
, because as you said about the doc the delete event will not be cascaded for StoredImageSize elements ! And do the same as above in the deleting
method of StoredFileObserver
:)
Assuming that the App\StoredImageSize
has reference to the physical files on the disk
$file = StoredFile::find(1);
foreach($file->sizes as $size){
Storage::delete($size->file_location);
}
$file->sizes()->delete();
$file->delete()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With