我的项目中有2个Eloquent模型:App\StoredFile
和App\StoredImageSize
。
StoredFile
模型负责保留上传的文件信息。如果上传的文件是图像,那么2个缩略图将存储在存储中,其属性将存储在DB(StoredImageSize
模型)中。
关系如下:
StoredFile.php:
public function sizes()
{
return $this->hasMany('App\StoredImageSize');
}
StoredImageSize.php:
public function originalImage()
{
return $this->belongTo('App\StoredFile');
}
StoredImageSize
有一个观察者类(StoredImageSizeObserver
),它已通过ServiceProvider注册并运行良好。
问题是我想从数据库中删除后续行时从存储中删除实际文件(在我的情况下是硬盘)。
StoredImageSizeObserver.php:
public function deleting(StoredImageSize $file)
{
Storage::delete($file->server_url);
}
逻辑是这样的:
$file = StoredFile::find(1);
$file->sizes()->delete(); // it does delete all related rows from 'StoredImageSize' but not files from storage
$file->delete()
实际上它永远不会从deleting
类点击StoredImageSizeObserver
方法,因为Laravel documentation说:
通过Eloquent执行批量删除语句时,不会为已删除的模型触发删除和删除的模型事件。这是因为在执行delete语句时,实际上从未检索过模型。
那么,我该如何应对这种情况呢?任何解决方案或建议将不胜感激。
答案 0 :(得分:3)
在StoredFile
模型中添加以下方法,您有两个选择:
第一个:
protected static function boot() {
parent::boot();
static::deleting(function(StoredFile $fileToDelete) {
foreach ($fileToDelete->sizes as $size)
{
$size->delete();
}
$fileToDelete->delete()
});
}
第二个:
protected static function boot() {
parent::boot();
static::deleting(function(StoredFile $fileToDelete) {
$size_ids = $fileToDelete->sizes()->lists('id');
StoredImageSize::whereIn($size_ids)->delete();
$fileToDelete->delete()
});
}
或者为StoredFile
模型创建一个观察者而不是StoredImageSize
,因为正如您所说的那样,删除事件不会为StoredImageSize元素级联!并在deleting
的{{1}}方法中执行与上述相同的操作:)
答案 1 :(得分:1)
假设App\StoredImageSize
引用了磁盘上的物理文件
$file = StoredFile::find(1);
foreach($file->sizes as $size){
Storage::delete($size->file_location);
}
$file->sizes()->delete();
$file->delete()