本文目录导读:

我来为您详细介绍如何为PHP项目实现软删除功能。
数据库设计
在数据表中添加软删除相关字段:
ALTER TABLE users ADD COLUMN deleted_at TIMESTAMP NULL DEFAULT NULL, ADD COLUMN deleted_by INT NULL DEFAULT NULL;
或者创建表时直接包含:
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100),
email VARCHAR(100),
deleted_at TIMESTAMP NULL DEFAULT NULL,
deleted_by INT NULL DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
PHP Trait实现(推荐方式)
创建可复用的Trait:
<?php
// SoftDeletable.php
trait SoftDeletable
{
/**
* 软删除记录
* @param int $deletedBy 删除者ID
* @return bool
*/
public function softDelete($deletedBy = null)
{
$this->deleted_at = date('Y-m-d H:i:s');
$this->deleted_by = $deletedBy;
return $this->save();
}
/**
* 恢复软删除的记录
* @return bool
*/
public function restore()
{
$this->deleted_at = null;
$this->deleted_by = null;
return $this->save();
}
/**
* 检查记录是否已删除
* @return bool
*/
public function isDeleted()
{
return $this->deleted_at !== null;
}
/**
* 强制删除记录
* @return bool
*/
public function forceDelete()
{
return parent::delete();
}
}
基础模型类实现
<?php
// BaseModel.php
class BaseModel
{
protected $table;
protected $primaryKey = 'id';
protected $fillable = [];
protected $db;
// 使用软删除Trait
use SoftDeletable;
/**
* 重写查询方法,自动过滤已删除记录
*/
public static function query()
{
$model = new static();
$model->where('deleted_at IS NULL');
return $model;
}
/**
* 查询包括已删除的记录
*/
public static function withTrashed()
{
return new static();
}
/**
* 只查询已删除的记录
*/
public static function onlyTrashed()
{
$model = new static();
$model->where('deleted_at IS NOT NULL');
return $model;
}
/**
* 删除方法重写
*/
public function delete()
{
return $this->softDelete();
}
}
具体模型类示例
<?php
// User.php
class User extends BaseModel
{
protected $table = 'users';
protected $fillable = ['name', 'email'];
// 业务方法
public function getActiveUsers()
{
return self::query()->get();
}
public function getDeletedUsers()
{
return self::onlyTrashed()->get();
}
}
使用示例
<?php
// 使用示例
// 1. 创建用户
$user = new User();
$user->name = '张三';
$user->email = 'zhangsan@example.com';
$user->save();
// 2. 软删除用户
$user->softDelete(1); // 参数为删除者ID
// 或者直接调用delete方法
$user->delete();
// 3. 查询活跃用户(自动过滤已删除)
$activeUsers = User::query()->get();
// 4. 查询所有用户(包括已删除)
$allUsers = User::withTrashed()->get();
// 5. 只查询已删除用户
$deletedUsers = User::onlyTrashed()->get();
// 6. 恢复用户
$user->restore();
// 7. 强制物理删除
$user->forceDelete();
// 8. 检查是否被删除
if ($user->isDeleted()) {
echo "该用户已被删除";
}
PDO数据库连接示例
<?php
// Database.php
class Database
{
protected static $instance = null;
protected $connection;
private function __construct()
{
$host = 'localhost';
$dbname = 'your_database';
$username = 'root';
$password = '';
try {
$this->connection = new PDO(
"mysql:host=$host;dbname=$dbname;charset=utf8mb4",
$username,
$password,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ
]
);
} catch (PDOException $e) {
die("连接失败: " . $e->getMessage());
}
}
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function getConnection()
{
return $this->connection;
}
}
完整示例的CRUD操作
<?php
// UserRepository.php
class UserRepository
{
private $db;
public function __construct()
{
$this->db = Database::getInstance()->getConnection();
}
/**
* 创建用户
*/
public function create($data)
{
$sql = "INSERT INTO users (name, email, created_at)
VALUES (:name, :email, NOW())";
$stmt = $this->db->prepare($sql);
$stmt->execute([
':name' => $data['name'],
':email' => $data['email']
]);
return $this->db->lastInsertId();
}
/**
* 软删除用户
*/
public function softDelete($id, $deletedBy = null)
{
$sql = "UPDATE users SET
deleted_at = NOW(),
deleted_by = :deleted_by
WHERE id = :id AND deleted_at IS NULL";
$stmt = $this->db->prepare($sql);
return $stmt->execute([
':id' => $id,
':deleted_by' => $deletedBy
]);
}
/**
* 恢复用户
*/
public function restore($id)
{
$sql = "UPDATE users SET
deleted_at = NULL,
deleted_by = NULL
WHERE id = :id";
$stmt = $this->db->prepare($sql);
return $stmt->execute([':id' => $id]);
}
/**
* 获取活跃用户
*/
public function getActiveUsers()
{
$sql = "SELECT * FROM users WHERE deleted_at IS NULL";
$stmt = $this->db->query($sql);
return $stmt->fetchAll();
}
/**
* 获取所有用户(包括已删除)
*/
public function getAllUsers()
{
$sql = "SELECT * FROM users ORDER BY created_at DESC";
$stmt = $this->db->query($sql);
return $stmt->fetchAll();
}
}
高级特性
1 自动软删除关联模型
<?php
trait CascadeSoftDeletes
{
protected $cascadeDeletes = [];
public function softDelete($deletedBy = null)
{
// 先删除关联模型
foreach ($this->cascadeDeletes as $relation) {
if (method_exists($this, $relation)) {
$relatedModels = $this->$relation()->get();
foreach ($relatedModels as $model) {
$model->softDelete($deletedBy);
}
}
}
return parent::softDelete($deletedBy);
}
}
2 软删除审计日志
<?php
trait SoftDeleteAudit
{
public function softDelete($deletedBy = null)
{
$result = parent::softDelete($deletedBy);
if ($result) {
// 记录审计日志
AuditLog::create([
'action' => 'soft_delete',
'model' => get_class($this),
'model_id' => $this->id,
'user_id' => $deletedBy,
'timestamp' => date('Y-m-d H:i:s')
]);
}
return $result;
}
}
注意事项
- 索引优化:为
deleted_at字段添加索引 - 唯一约束:注意软删除记录的唯一约束问题
- 查询性能:大量软删除记录可能影响查询性能
- 数据清理:定期清理物理删除过期数据
- 备份策略:软删除不应该替代数据备份
这就是一个完整的PHP软删除实现方案,可以根据项目需求进行适当调整和扩展。