悠悠楠杉
PHP框架实现数据软删除功能的实用技巧
一、什么是软删除?
软删除(Soft Delete)是数据库操作中的一种逻辑删除方式,与物理删除的最大区别在于:数据不会真正从数据库消失,而是通过特定字段标记为"已删除"状态。这种设计在以下场景中尤为重要:
- 需要保留数据追溯性的系统
- 可能存在误删的C端用户数据
- 需要数据恢复功能的业务场景
二、Laravel框架的优雅实现
1. 基础配置
Laravel通过Eloquent ORM内置了开箱即用的软删除功能:
php
// 模型中引入SoftDeletes特性
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
}
2. 数据库迁移
需要添加deleted_at
字段(默认字段名):
php
Schema::table('users', function (Blueprint $table) {
$table->softDeletes(); // 等同于timestamp('deleted_at')->nullable()
});
3. 核心操作示例
php
// 软删除操作
$user->delete();
// 查询时自动过滤已删除数据
User::all();
// 包含已删除数据查询
User::withTrashed()->get();
// 仅查询已删除数据
User::onlyTrashed()->get();
// 恢复数据
User::withTrashed()->find(1)->restore();
三、ThinkPHP的实现方案
ThinkPHP6.x版本通过软删除 trait 实现类似功能:
php
use think\model\concern\SoftDelete;
class User extends Model
{
use SoftDelete;
protected $deleteTime = 'delete_time'; // 自定义字段名
}
操作方式与Laravel类似:php
// 软删除
User::destroy(1);
// 强制删除(物理删除)
User::destroy(1, true);
四、深度优化技巧
1. 性能优化
- 索引优化:为
deleted_at
字段添加索引
php $table->index('deleted_at');
- 查询作用域:自定义默认查询范围
php // 在模型中添加 protected static function boot() { parent::boot(); static::addGlobalScope('active', function ($builder) { $builder->whereNull('deleted_at'); }); }
2. 多租户场景处理
当系统需要区分不同租户的删除数据时:php
// 添加租户标识字段
$table->unsignedInteger('tenant_id')->index();
// 查询时自动附加条件
User::onlyTrashed()
->where('tenantid', auth()->user()->tenantid)
->get();
3. 数据归档策略
对于长期不用的软删除数据,建议定期归档:php
// 创建归档表(结构与原表相同)
Schema::create('usersarchive', function (Blueprint $table) {
$table->increments('id');
// 其他字段...
$table->timestamp('deletedat');
});
// 定时任务处理(示例代码)
$expiredDate = now()->subYear();
User::onlyTrashed()
->where('deleted_at', '<', $expiredDate)
->chunk(200, function ($users) {
foreach ($users as $user) {
// 写入归档表
ArchiveUser::create($user->toArray());
// 物理删除
$user->forceDelete();
}
});
五、常见问题解决方案
关联数据级联删除
使用模型事件处理关联数据:php
protected static function boot()
{
parent::boot();static::deleting(function ($user) {
if ($user->isForceDeleting()) {
// 物理删除时的处理
} else {
// 软删除时的关联处理
$user->posts()->delete();
}
});
}唯一索引冲突
对于需要保持唯一性的字段(如email),解决方案:
sql CREATE UNIQUE INDEX users_email_unique ON users (email) WHERE deleted_at IS NULL;
数据恢复校验
恢复前验证数据有效性:php
public function restoreUser($id)
{
$user = User::withTrashed()->find($id);if ($user->trashed() && !$user->email_exists) {
return $user->restore();
}throw new Exception('恢复条件不满足');
}
通过合理实现软删除功能,可以在保证数据安全性的同时,满足业务系统的灵活性需求。不同框架的实现原理类似,关键在于根据实际业务场景选择合适的优化策略。