Laravel 5.5 模型上的自定义软删除

Posted

技术标签:

【中文标题】Laravel 5.5 模型上的自定义软删除【英文标题】:Laravel 5.5 Custom Soft Deletes on Model 【发布时间】:2018-06-19 19:56:06 【问题描述】:

我的帖子通过status 列中的值定义为软删除与否,其中:0 = 不可用,1 = 可用,77 = 软删除。

目前,我在模型中添加了一个全局范围,以确保我不会返回软删除的帖子:

protected static function boot()

    parent::boot();

    static::addGlobalScope('status', function (Builder $builder) 
        $builder->where('status', '!=', '77');
    );

我将如何修改模型的 softDelete(laravel 内置功能)从其默认的时间戳和 deleted_at 列使用我的基于数字/状态的系统,甚至/特别是在使用诸如 ->delete() 之类的方法时工作、->withTrashed()->restore()?

【问题讨论】:

【参考方案1】:

你需要插入到模型使用类中:

use Illuminate\Database\Eloquent\SoftDeletes;

还需要在类声明中插入:

use SoftDeletes;

https://laravel.com/docs/5.5/eloquent#soft-deleting

【讨论】:

要在模型中添加自定义方法delete(),您需要在模型中重新声明方法delete 编辑Illuminate\Database\Eloquent\SoftDeletes; 会改变所有模型的默认行为,对吗?我只需要为此模型编辑的 softDelete 功能... 只需在模型中创建自己的方法delete 你能不能扩展一下 - 我对在哪里以及到底放什么感到困惑:P 在该模型中创建一个名为 softDelete() 的方法,该方法填充了您的逻辑。如果您调用 $model->softDelete() 它将使用该方法。我会删除使用 Illuminate\Database\Eloquent\SoftDeletes;从那个模型,因为你实际上并没有使用它。【参考方案2】:

您可以查看 Laravel 的模型事件部分。在您的模型中,扩展您创建的 baseModel 类。在此 baseModel 中,您可以添加在模型删除时触发的事件。像这样:

protected static function boot()
    static::deleting(function($thisModel)
        $thisModel->attributes['status'] = 77;
        $thisModel->save();
        return false;
    );

当您返回 false 时,您将停止删除模型的默认操作。因此,这会将状态设置为 77 而不是将其删除。或者你可以在任何你想使用这种删除的模型中使用它,而不是使用基本模型。我发现基本模型对于有一些可以实现基于状态的软删除的大型项目来说更容易。

要扩展在此模型中添加其他类似软删除的功能,请考虑使用本地范围而不是列出的全局范围。例如:

public function scopeOnlyTrashed(Builder $query)
    return $query->where('status', 77);

现在当你调用数据库时

Posts::onlyTrashed()->get();

你将获得与 laravel 的 onlyTrashed() 方法相同的功能。

【讨论】:

这会单独理解->onlyTrashed()之类的东西吗? 我不这么认为。这只是停止尝试删除记录的默认行为。当然, ->onlyTrashed() 只会变成 ->where('status', 77) 并且功能相同。 在进一步阅读 SoftDeletes 类之后,垃圾方法似乎都依赖于模型的 deleted_at 列。因此,没有它,laravel 就无法确定什么是垃圾,什么不是垃圾。 所以我必须完全重写 softDeletes 的逻辑 - 关于如何复制该类并使其仅影响该模型的任何好主意? 这听起来像是一项小工作的大任务。由于它是基于状态的并且不使用 Laravel 的默认软删除方案,因此我将仅利用模型事件进行 delete(),并将您正在使用的全局范围设置为模型的本地范围。如果将范围设为本地,则可以在检索该模型的集合时调用它。使用其中一些范围,您将拥有与 withTrashed()、onlyTrashed() 等非常相似的功能。只需将其称为 scopeWithTrashed() 并让查询返回所有模型,scopeOnlyTrashed() 将仅返回具有状态的模型77 个。【参考方案3】:

您可以在存储库中定义一个方法,如下所示:

class YourRepository extends BaseRepository 

    public function withTrashed() 
        $this->model = $this->model->withTrashed();
        return $this;
     

之后,您可以在控制器中链接相同的内容:

$records = $this->repository->withTrashed()->all();

【讨论】:

以上是关于Laravel 5.5 模型上的自定义软删除的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 会话立即过期(Laravel 5.5)

用户模型 laravel 中的自定义表

相关模型 eloquent laravel 中的自定义查询

laravel 关系集合上的自定义排序

在没有类依赖的自定义类/子系统中使用 Laravel 4 模型

如何从 Laravel 8 中的自定义 Web 路由中删除“api/”前缀?