软删除字段未加到 $casts 会导致 restore() 静默失败;必须声明 protected $casts = ['deleted_at' => 'datetime'],并确保数据库字段为 TIMESTAMP/DATETIME 类型且可空。

软删除字段没加到 $casts 会导致恢复失败
软删除本质是给记录打个标记,不是真删。Laravel 默认用 deleted_at 字段存时间戳,但如果这个字段没在模型里声明为日期类型,restore() 会静默失败——查不到记录、也不报错,只返回 false。
- 必须在模型中加:
protected $casts = ['deleted_at' => 'datetime']; - 如果用的是 MySQL 的
NULL默认值,字段类型得是TIMESTAMP或DATETIME,不能是INT或字符串 - 迁移里别漏掉
softDeletes():$table->softDeletes();(它等价于$table->timestamp('deleted_at')->nullable();)
查询已软删除记录要用 withTrashed() 或 onlyTrashed()
默认的 find()、where() 都自动排除 deleted_at IS NOT NULL 的行。想查“已删但还在库里的”,得显式告诉 Eloquent 别过滤。
-
User::withTrashed()->find(123):查 ID=123 的记录,不管删没删 -
User::onlyTrashed()->where('email', 'test@example.com')->first():只查已被软删除的匹配项 -
withTrashed()会把deleted_at IS NULL OR deleted_at IS NOT NULL加进 WHERE,性能略差,慎用于大表分页
restore() 不触发 creating/created 等事件,但会触发 restored
软删除恢复不是重新插入,所以不会走创建生命周期。如果你依赖 created 事件写日志或发通知,得改用 restored 事件。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
- 在模型里监听:
protected $dispatchesEvents = ['restored' => UserRestored::class]; -
restore()返回布尔值:true表示成功恢复(即该记录确实处于软删除状态),false表示记录不存在或本就没删 - 批量恢复要注意:
User::onlyTrashed()->where('team_id', 5)->restore()是可行的,但事务中需留意锁行为
硬删前没 check softDeleted() 可能误删真实数据
有人想“彻底删掉某条软删除记录”,直接调 delete(),结果发现这条记录被物理删了——因为 delete() 在已软删除的模型实例上,会执行硬删。
- 安全做法是先判断:
if ($user->trashed()) { $user->forceDelete(); } -
forceDelete()才是明确的物理删除,且会触发forceDeleted事件 - 别对刚
find()出来的模型直接delete(),除非你确认它没被软删除过
软删除不是开关,是状态叠加。一次 restore() 后再 delete(),又回到软删除状态;只有 forceDelete() 或原生 SQL 才真正擦除。










