ci框架需通过字段设计(is_deleted、deleted_at等)、联合唯一索引或备份表解决冲突、模型层封装delete/restore/purge方法及关联查询过滤,实现闭环软删除。

CI框架本身不内置软删除机制,但可以通过字段设计+手动逻辑+模型层封装,实现类似“回收站”的软删除能力。关键不是加个字段就完事,而是让标记、过滤、还原、清理形成闭环。
核心字段设计:兼顾唯一性与可恢复性
在需要软删除的表中,至少新增两个字段:
- is_deleted:TINYINT(1) DEFAULT 0 NOT NULL,值为 0(正常)、1(已删除),用于快速筛选和索引;
- deleted_at:DATETIME NULL DEFAULT NULL,记录删除时间,便于排序、归档和审计;
- (可选)deleted_by:INT UNSIGNED NULL,记录操作人ID,增强追溯能力。
注意:不要仅用 deleted_at IS NULL 判断状态——NULL 值在联合索引、JOIN 和 COUNT 中行为不稳定,且无法区分“从未删过”和“删了但没记时间”。is_deleted 是主控开关,deleted_at 是辅助信息。
唯一约束冲突问题必须提前解决
软删除后原记录仍占着 UNIQUE KEY(比如 username、mobile、code 等),新数据无法复用相同值,这是 CI 项目中最常见的翻车点。解决方案有二:
- 将原唯一字段与
is_deleted组成联合唯一索引:ALTER TABLE users ADD UNIQUE KEY uk_username_deleted (username, is_deleted);
这样允许同一 username 多次出现,只要其中最多一个is_deleted = 0; - 若业务强要求全局唯一(如身份证号),可改用 逻辑删除+备份表方案:删除时把整行 INSERT 到
users_deleted表,再从原表物理删除。回收站列表直接查备份表,还原即回插+清空备份行。
CI 模型层封装:统一拦截增删改查
CodeIgniter 没有 ORM 自动逻辑删除,必须靠模型方法显式控制:
-
删除操作:重写
delete()方法,改为UPDATE SET is_deleted = 1, deleted_at = NOW(), deleted_by = ?; -
查询操作:默认所有
get()、get_where()都自动附加AND is_deleted = 0条件;需查回收站时,提供get_trashed()或with_trashed()方法; -
还原操作:新增
restore($id)方法,执行UPDATE ... SET is_deleted = 0, deleted_at = NULL, deleted_by = NULL WHERE id = ? AND is_deleted = 1; -
彻底删除:管理后台提供“清空回收站”,调用
purge_trash()执行真实DELETE FROM ... WHERE is_deleted = 1(建议加定时任务+低峰期执行)。
回收站页面与关联数据处理
用户看到的“回收站”本质是 WHERE is_deleted = 1 的列表,但要注意:
- 关联查询(如订单→用户、文章→分类)需在 JOIN 条件中同步过滤:
LEFT JOIN users u ON u.id = o.user_id AND u.is_deleted = 0,避免展示已删用户信息; - 统计类需求(如“共删除 127 条”)应单独查
COUNT(*) FROM table WHERE is_deleted = 1,别混在主列表 SQL 里; - 前端列表支持批量还原/批量清除,后端需校验权限,并记录操作日志(谁、何时、还原了哪些 ID)。
不复杂但容易忽略细节。











