需用模型force()机制定期物理清理软删除超30天数据:先确认模型启用softdelete、$usesoftdelete=true、delete_time字段存在且配置正确,再通过命令行任务调用onlytrashed()->where('delete_time', '

你需要在ThinkPHP 6.0项目中,定期把已软删除超过30天的数据真正从数据库里删掉,而不是一直堆积在表里占用空间、拖慢查询速度。这不能靠手动执行SQL,必须用模型层的force()机制触发事件钩子,同时避免并发冲突和误删。
确认软删除配置已生效
先验证模型是否真正启用软删除:打开对应模型文件(如app\model\User.php),检查是否同时满足三项——【use think\model\concern\SoftDelete;】、【use SoftDelete;】、【protected $useSoftDelete = true;】。缺一不可,否则delete()会直接物理删除,后续force()也无效。
数据库中对应表必须有delete_time字段,类型为DATETIME NULL DEFAULT NULL;若字段名不是delete_time,模型里要显式声明protected $deleteTime = 'xxx';。
执行php think optimize:schema命令刷新模型缓存,否则旧结构可能导致onlyTrashed()查不到数据。
编写物理清理命令行任务
在app/command目录下新建CleanSoftDeleted.php:
复制以下代码到文件中,注意替换App\Model\User为你实际的模型类名,并调整时间条件(此处为30天前):
```php
namespace app\command;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Db;
use app\model\User;
class CleanSoftDeleted extends Command
{
protected function configure()
{
$this->setName('clean:softdeleted')
->setDescription('物理清理软删除超过30天的数据');
}
protected function execute(Input $input, Output $output)
{
$thirtyDaysAgo = date('Y-m-d H:i:s', strtotime('-30 days'));
// 先统计数量,写入日志便于追溯
$count = User::onlyTrashed()
->where('delete_time', ' ->count();
$output->writeln("待物理删除记录数:{$count}");
if ($count === 0) {
$output->writeln('无符合条件数据,退出');
return 0;
}
// 开启事务,确保关联清理不中断
Db::transaction(function () use ($thirtyDaysAgo, $output) {
User::onlyTrashed()
->where('delete_time', ' ->force()
->delete();
$output->writeln('物理删除成功');
});
}
}
保存后,在项目根目录执行php think make:command clean:softdeleted注册命令(若未自动注册)。
配置Crontab定时触发
第一步:测试命令能否正常运行
在终端执行php think clean:softdeleted,观察是否输出“物理删除成功”且数据库中对应记录消失。失败时重点检查模型路径、字段名、时间格式是否匹配。
第二步:编辑服务器crontab
执行crontab -e,添加一行(假设项目路径为/var/www/myapp):
【0 2 * * * cd /var/www/myapp && /usr/bin/php think clean:softdeleted >> /var/log/think-clean.log 2>&1】
这表示每天凌晨2点执行一次。注意必须用绝对路径调用php,否则cron环境找不到PHP可执行文件。
第三步:加flock防并发(关键!)
如果清理脚本执行时间可能超过1分钟(比如删几万条),需防止cron重复启动实例导致锁表或重复删除。修改crontab为:
0 2 * * * cd /var/www/myapp && flock -n /tmp/clean_softdeleted.lock -c "/usr/bin/php think clean:softdeleted >> /var/log/think-clean.log 2>&1"
验证与日志监控
方法一:查看日志文件
执行tail -f /var/log/think-clean.log,观察每次执行是否输出“待物理删除记录数:X”和“物理删除成功”。若出现PHP错误或MySQL超时,日志会明确记录。
方法二:手动模拟过期数据
在数据库中执行UPDATE user SET delete_time = '2025-01-01 00:00:00' WHERE id = 123;,再运行php think clean:softdeleted,确认该记录被真正删除而非仅更新delete_time。
方法三:检查事务安全性
故意在execute()方法中throw new \Exception('test rollback');,再次运行命令,确认原记录未被删除——说明事务回滚生效,关联清理逻辑安全。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











