本文目录导读:

在 PHP 中实现软删除有几种常见方式,我来详细介绍:
使用数据库字段实现(最基础)
创建表结构
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100),
email VARCHAR(100),
deleted_at TIMESTAMP NULL DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
基础 PHP 实现
<?php
class User {
private $db;
public function __construct($pdo) {
$this->db = $pdo;
}
// 软删除
public function softDelete($id) {
$sql = "UPDATE users SET deleted_at = NOW() WHERE id = ? AND deleted_at IS NULL";
$stmt = $this->db->prepare($sql);
return $stmt->execute([$id]);
}
// 查询未删除的用户
public function getActiveUsers() {
$sql = "SELECT * FROM users WHERE deleted_at IS NULL";
$stmt = $this->db->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// 查询包含已删除的用户
public function getAllUsers() {
$sql = "SELECT * FROM users";
$stmt = $this->db->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// 恢复被删除的用户
public function restore($id) {
$sql = "UPDATE users SET deleted_at = NULL WHERE id = ?";
$stmt = $this->db->prepare($sql);
return $stmt->execute([$id]);
}
// 永久删除
public function forceDelete($id) {
$sql = "DELETE FROM users WHERE id = ?";
$stmt = $this->db->prepare($sql);
return $stmt->execute([$id]);
}
}
?>
使用 Trait 复用(面向对象方式)
<?php
trait SoftDeletes {
public $deletedAt = 'deleted_at';
// 软删除
public function softDelete() {
if (!$this->exists()) {
return false;
}
$this->{$this->deletedAt} = date('Y-m-d H:i:s');
return $this->save();
}
// 恢复
public function restore() {
if ($this->{$this->deletedAt} === null) {
return false;
}
$this->{$this->deletedAt} = null;
return $this->save();
}
// 永久删除
public function forceDelete() {
return $this->delete(true);
}
// 检查是否已软删除
public function isTrashed() {
return !empty($this->{$this->deletedAt});
}
// 查询作用域
public static function withTrashed() {
// 返回包含已删除记录的查询
}
public static function onlyTrashed() {
// 只返回已删除的记录
}
}
class User {
use SoftDeletes;
protected $table = 'users';
// 重写 delete 方法支持软删除
public function delete($force = false) {
if (!$force && $this->{$this->deletedAt} === null) {
return $this->softDelete();
}
return parent::delete();
}
}
?>
使用 PDO 实现完整的软删除封装
<?php
abstract class Model {
protected $db;
protected $table;
protected $primaryKey = 'id';
protected $fillable = [];
protected $softDelete = true;
protected $deletedAt = 'deleted_at';
public function __construct($pdo) {
$this->db = $pdo;
}
// 删除操作
public function delete($id) {
if ($this->softDelete) {
return $this->softDeleteRecord($id);
}
return $this->forceDeleteRecord($id);
}
// 软删除实现
private function softDeleteRecord($id) {
$sql = "UPDATE {$this->table}
SET {$this->deletedAt} = :deleted_at
WHERE {$this->primaryKey} = :id
AND {$this->deletedAt} IS NULL";
$stmt = $this->db->prepare($sql);
$stmt->bindValue(':deleted_at', date('Y-m-d H:i:s'));
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
return $stmt->execute();
}
// 永久删除
private function forceDeleteRecord($id) {
$sql = "DELETE FROM {$this->table} WHERE {$this->primaryKey} = :id";
$stmt = $this->db->prepare($sql);
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
return $stmt->execute();
}
// 查询所有记录的 where 条件构建
protected function buildWhereForActive($query) {
if ($this->softDelete) {
$query .= " AND {$this->deletedAt} IS NULL";
}
return $query;
}
// 查找单个记录
public function find($id) {
$sql = "SELECT * FROM {$this->table}
WHERE {$this->primaryKey} = ?";
if ($this->softDelete) {
$sql .= " AND {$this->deletedAt} IS NULL";
}
$stmt = $this->db->prepare($sql);
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
// 获取所有记录
public function all($includeTrashed = false) {
$sql = "SELECT * FROM {$this->table}";
if (!$includeTrashed && $this->softDelete) {
$sql .= " WHERE {$this->deletedAt} IS NULL";
}
$stmt = $this->db->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
}
?>
使用现成框架(推荐)
Laravel 实现
<?php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model {
use SoftDeletes;
protected $table = 'users';
protected $dates = ['deleted_at'];
}
// 使用
$user = User::find(1);
$user->delete(); // 软删除
// 查询
$activeUsers = User::all(); // 只查未删除的
$allUsers = User::withTrashed()->get(); // 查所有
$onlyDeleted = User::onlyTrashed()->get(); // 只查已删除的
// 恢复
$user = User::withTrashed()->find(1);
$user->restore();
// 永久删除
$user->forceDelete();
?>
ThinkPHP 实现
<?php
namespace app\model;
use think\Model;
use think\model\concern\SoftDelete;
class User extends Model {
use SoftDelete;
protected $deleteTime = 'delete_time';
}
// 使用
$user = User::find(1);
$user->delete(); // 软删除
// 查询
$users = User::select(); // 只查未删除的
$all = User::withTrashed()->select(); // 查所有
$deleted = User::onlyTrashed()->select(); // 查已删除的
// 恢复
$user = User::onlyTrashed()->find(1);
$user->restore();
?>
MySQL 触发器方式(极端情况)
-- 创建触发器自动设置 deleted_at
DELIMITER //
CREATE TRIGGER before_delete_users
BEFORE DELETE ON users
FOR EACH ROW
BEGIN
UPDATE users
SET deleted_at = NOW()
WHERE id = OLD.id AND deleted_at IS NULL;
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Soft delete only - cannot hard delete';
END//
DELIMITER ;
-- 但通常不推荐这种方案,因为灵活性差
最佳实践建议:
- 统一约定:字段
deleted_at使用NULL表示未删除,有值表示已删除时间 - 索引优化:为
deleted_at字段建立索引,提高查询效率 - 统一方法:封装统一的软删除、恢复、永久删除方法
- 框架优先:如果使用框架,优先使用框架的内置软删除功能
- 定时清理:定期清理长时间未恢复的软删除数据
- 注意查询:记得在业务查询中过滤
deleted_at IS NULL条件
选择哪种方式取决于项目的规模、使用的框架和个人偏好,对于中小型项目,直接使用数据库字段和简单封装就足够了。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播