Pruning 是 Laravel 10.28+ 的软性清理机制,仅在执行 php artisan model:prune 时触发删除,并非自动运行;需重写 prunable() 方法定义过期逻辑,否则默认不清理。

Pruning 是什么,它真能自动删数据?
Pruning 不是定时任务,也不是后台守护进程——它是 Laravel 10.28+ 引入的「软性清理机制」,只在你执行 php artisan model:prune 时才真正触发删除。它不自动运行,也不会在每次请求中检查过期模型。所谓“自动”,仅指「自动识别哪些该删」,而非「自动执行删除」。
所以别指望它替代 schedule()->command('model:prune'),更不能靠它实时清理缓存或会话表。
怎么给模型加 Pruning?必须重写 prunable() 吗?
不是必须重写,但几乎总是要重写。默认 prunable() 返回空查询,相当于关掉了该模型的清理能力。你要显式定义过期逻辑,比如:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Prunable;
class PasswordReset extends Model
{
use Prunable;
public function prunable(): Builder
{
return static::where('created_at', 'subHours(2));
}
}
注意:返回值必须是 Builder 实例(即 Eloquent 查询构造器),不能是数组、布尔值或直接调用 delete()。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
-
prunable()内部不能用$this,因为它是静态上下文 - 别在
prunable()里做复杂关联查询,性能差且可能漏删(Pruning 走的是单表DELETE FROM ... WHERE) - 如果模型用了软删除(
SoftDeletes),Pruning 默认跳过已软删记录——它只处理「存活但过期」的数据
运行 php artisan model:prune 时为什么没删任何记录?
常见原因有三个:
- 模型没声明
use Prunable;,或者命名空间没引入Illuminate\Database\Eloquent\Prunable -
prunable()方法名拼错(比如写成pruneable()或prunabel()),Laravel 完全静默忽略 - 数据库时区和 PHP 时区不一致,比如 MySQL 用
SYSTEM时区(CST),而now()返回的是 PHP 的 UTC 时间,导致条件永远不匹配
调试技巧:临时在 prunable() 中加 dd($this->toSql())(注意要先调用 toBase()),看生成的 SQL 是否符合预期;或手动执行该 SQL 验证结果集。
能不能只对某些环境启用 Pruning?
可以,但得靠代码控制,不是配置开关。例如:
model:prune
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










