Laravel软删除需同时配置模型SoftDeletes trait和数据库deleted_at字段,否则delete()执行硬删;验证时默认查询不返回软删记录,可用withTrashed()等方法显式操作。

如果您在Laravel中调用模型的delete()方法后发现数据彻底消失、无法恢复,或查询时始终看不到已“删除”的记录,则很可能是软删除功能未正确启用。软删除并非默认行为,必须显式配置模型与数据库结构才能生效。以下是实现该功能的多种方法:
一、配置模型并添加数据库字段
此方法是启用软删除的基础前提,缺一不可:模型需引入SoftDeletes trait,数据表必须包含deleted_at字段。二者任一缺失都将导致delete()执行硬删或报错。
1、运行命令创建迁移文件:php artisan make:migration add_deleted_at_to_users_table --table=users
2、在迁移文件的up()方法中添加:$table->softDeletes();
3、执行迁移:php artisan migrate
4、在对应模型(如app/Models/User.php)顶部引入trait:use Illuminate\Database\Eloquent\SoftDeletes;
5、在模型类定义中声明trait:use SoftDeletes;
6、(可选但推荐)显式声明日期字段:protected $dates = ['deleted_at'];,确保deleted_at被自动转换为Carbon实例
二、使用预置迁移命令快速启用
此方法适用于新模型或新建表场景,通过Artisan命令直接生成含softDeletes()的完整建表迁移,避免手动修改已有迁移。
1、执行命令生成建表迁移:php artisan make:migration create_posts_table
2、在迁移文件的up()方法中,于Schema::create()闭包内添加:$table->softDeletes();
3、运行迁移:php artisan migrate
4、在Post模型中引入并使用SoftDeletes trait
5、验证配置:调用$post->delete()后检查数据库,确认deleted_at字段被设为当前时间戳而非记录被移除
三、对已有模型追加软删除支持
当模型已存在且表结构已上线时,此方法通过独立迁移补全deleted_at字段,无需重建表或丢失现有数据。
1、运行命令创建独立字段迁移:php artisan make:migration add_soft_deletes_to_comments_table
2、在新迁移的up()方法中写入:Schema::table('comments', function (Blueprint $table) { $table->softDeletes(); });
3、执行迁移:php artisan migrate
4、打开Comment模型文件,在class声明前加入:use Illuminate\Database\Eloquent\SoftDeletes;
5、在class Comment extends Model花括号内第一行添加:use SoftDeletes;
6、关键验证步骤:必须重启应用缓存或清空配置缓存(php artisan config:clear)以确保Eloquent识别新字段
四、启用后验证与基础操作
完成配置后,需验证软删除机制是否按预期工作:普通查询自动过滤,而特定方法可显式访问不同状态的数据。
1、执行软删除:$user = User::find(5); $user->delete();
2、验证默认查询不返回该记录:User::find(5)返回null
3、查询全部(含软删):User::withTrashed()->find(5)应返回模型实例
4、仅查软删记录:User::onlyTrashed()->where('id', 5)->first()
5、恢复单条记录:User::withTrashed()->find(5)->restore();
6、强制物理删除(不可逆):User::withTrashed()->find(5)->forceDelete();
五、处理关联模型的软删除联动
父模型软删除时,子模型默认不会自动标记为软删除,需手动干预以维持业务逻辑一致性。
1、在父模型(如User)中监听deleting事件:
2、在boot()方法内注册闭包:static::deleting(function ($user) { $user->posts()->update(['deleted_at' => now()]); });
3、确保Post模型自身也启用了SoftDeletes trait及deleted_at字段
4、恢复父模型时,子模型仍需单独恢复:$user->posts()->withTrashed()->restore();
5、重要提示:外键约束中的onDelete('cascade')对软删除完全无效,仅响应硬删操作


















