Laravel:设置未来deleted_at后模型被误判软删除,如何解决?
问题:Laravel Eloquent 软删除提前判定异常
我创建User模型实例时,将deleted_at字段设为当前时间加1小时,原本预期时间到期后自动触发软删除,但现在Eloquent直接把这条记录判定为已软删除状态。要求不将deleted_at设为null的前提下解决该问题。
当前现状
- 有效查询(能获取到记录):
$user = User::withTrashed()->where('id',15)->first();
- 无效查询(返回null):
$user = User::where('id',15)->first(); // 返回null
模型中设置deleted_at的代码
public static function boot() { parent::boot(); static::creating(function ($model) { $model->deleted_at = now()->addHour(); }); }
解决方案
Laravel默认的软删除逻辑是只要deleted_at不为null,就判定为已删除,所以要修改这个规则,让它只排除deleted_at小于等于当前时间的记录。直接在User模型中自定义全局作用域替换默认约束即可:
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletes; class User extends Model { use SoftDeletes; protected static function boot() { parent::boot(); // 替换默认软删除全局作用域 static::addGlobalScope('softDelete', function (Builder $builder) { $builder->where(function ($query) { // 保留未删除(deleted_at为null)和未到删除时间(deleted_at>当前时间)的记录 $query->whereNull('deleted_at') ->orWhere('deleted_at', '>', now()); }); }); static::creating(function ($model) { $model->deleted_at = now()->addHour(); }); } }
说明
- 修改后,默认查询(不用
withTrashed)会正常返回deleted_at大于当前时间的记录,直到时间到期后,该记录才会被自动过滤,此时需要用withTrashed才能查到。 - 手动调用
delete()方法时,Laravel会把deleted_at设为当前时间,此时该记录会立即被判定为已软删除,符合常规操作逻辑。
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

