如何为PHP项目实现软删除功能?

wen PHP项目 3

本文目录导读:

如何为PHP项目实现软删除功能?

  1. 数据库设计
  2. PHP Trait实现(推荐方式)
  3. 基础模型类实现
  4. 具体模型类示例
  5. 使用示例
  6. PDO数据库连接示例
  7. 完整示例的CRUD操作
  8. 高级特性
  9. 注意事项

我来为您详细介绍如何为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;
    }
}

注意事项

  1. 索引优化:为 deleted_at 字段添加索引
  2. 唯一约束:注意软删除记录的唯一约束问题
  3. 查询性能:大量软删除记录可能影响查询性能
  4. 数据清理:定期清理物理删除过期数据
  5. 备份策略:软删除不应该替代数据备份

这就是一个完整的PHP软删除实现方案,可以根据项目需求进行适当调整和扩展。

抱歉,评论功能暂时关闭!