CodeIgniter 4 的 Model 类本身不提供软删除功能,必须手动实现:需添加 deleted_at 字段、配置 $deletedField、重写 delete() 方法并控制查询逻辑。

CodeIgniter 4 的 Model 类**本身不提供软删除功能**,它没有内置类似 Laravel 的 SoftDeletes trait。所谓“CI4 模型自带软删除”是一种常见误解——CI4 的软删除必须**手动实现**,依赖开发者配置字段、重写方法并控制查询逻辑。
数据库表必须添加 deleted_at 字段
这是软删除的基础。该字段用于标记记录是否“已删除”,类型应为 TIMESTAMP 或 DATETIME,允许为空(NULL)。
- 在迁移文件中使用
$table->timestamp('deleted_at')->nullable(); - 不要用
date或integer类型,否则时间比较和自动填充会出错 - 确保字段名严格为
deleted_at(小写+下划线),后续逻辑将依赖此命名
模型中启用软删除逻辑(手动配置)
CI4 不会自动识别 deleted_at,需在模型中显式干预:
- 定义
protected $deletedField = 'deleted_at';—— 告诉模型该字段承担软删语义 - 启用时间戳(可选但推荐):
protected $useTimestamps = true;,并设置protected $deletedField = 'deleted_at'; - 在
$allowedFields中包含'deleted_at',否则update()无法写入该字段 - 若需默认隐藏已删除数据,重写
find()或findAll()方法,在查询时自动追加where('deleted_at IS NULL')
实现 delete() 的软删除行为
CI4 的 delete() 默认是硬删除。要改为软删,需在模型中覆盖该方法:
- 检查传入的 ID 是否存在,避免误操作整表
- 调用
$this->update($id, ['deleted_at' => date('Y-m-d H:i:s')])更新时间戳 - 返回布尔值或影响行数,保持与原方法签名一致
- 注意:不能只传
$data而不传$id,否则可能静默更新全表(CI4update()的经典陷阱)
查询已软删除/全部数据的处理方式
CI4 不会自动过滤或包含软删数据,所有逻辑需手动控制:
- 查正常数据(默认):直接用
$model->find($id)或$model->where()->first() - 查已软删数据:显式
$model->where('deleted_at IS NOT NULL')->findAll() - 查全部数据(含软删):去掉
deleted_at条件,或用 Query Builder 绕过模型封装:$this->db->table('users')->get() - 恢复数据:用
$model->update($id, ['deleted_at' => null])清空时间戳
注意事项与避坑点
软删除不是开箱即用的功能,容易因配置疏漏导致数据异常:
-
主键必须正确配置:模型中
$primaryKey必须与表实际主键一致,否则update($id, ...)无法定位目标行 -
$allowedFields 必须包含 deleted_at:否则软删操作会静默失败,返回
false -
避免混用硬删与软删逻辑:同一张表不应同时存在真实删除和软删,否则
deleted_at IS NULL判断失效 -
事务中慎用软删:若需回滚,要确保
deleted_at能被一并还原,建议在事务内统一用原生 SQL 控制

















