在Yii2.0.42中批量删除需绕过模型delete()以记录操作人,改用Command+手动日志:先获取$userId,再用Yii::info()记录action、table、condition等信息。

在 Yii2.0.42 中实现批量删除时记录操作人,关键在于**避开模型层的单条 delete() 调用**(它不触发 afterDelete 行为),改用可控、可注入上下文的方式,并确保用户身份信息能可靠传递到日志环节。
用 Command + 手动日志方式记录操作人
这是最直接、最可靠的方法,适用于 deleteAll()、createCommand()->delete() 等原生批量操作:
- 先获取当前登录用户 ID:
$userId = \Yii::$app->user->id ?? null;(注意判空,未登录时需处理) - 执行删除前,用
Yii::info()主动打点,把操作人、表名、条件、时间等一并写入日志:Yii::info(json_encode([ 'action' => 'batch_delete', 'table' => 'order', 'condition' => ['status' => 'cancelled', 'created_at' => ['<', $cutoff]], 'user_id' => $userId, 'ip' => \Yii::$app->request->getUserIP(), 'time' => date('Y-m-d H:i:s') ]), 'audit'); - 配置 log 组件的 targets,确保
categories => ['audit']被正确路由到 DbTarget 或 FileTarget
封装 deleteAll() 并统一注入用户上下文
避免到处重复写日志逻辑,可在基类或服务层封装一个带审计的批量删除方法:
- 定义一个公共方法,例如
UserService::safeDeleteAll($modelClass, $condition, $params = []) - 内部先查出将被删除的主键(如
$ids = $modelClass::find()->select('id')->where($condition)->column();) - 记录日志(含
$userId、$ids、操作类型) - 再调用
$modelClass::deleteAll($condition, $params)执行真实删除 - 这样既保留了 ActiveRecord 的便利性,又把操作人信息稳稳带上
慎用 LogBehavior 实现批量操作审计
LogBehavior 默认只对单模型的 insert/update/delete 生效,deleteAll() 完全绕过模型生命周期,不会触发任何行为。所以:
- 不要指望给 Model 配 LogBehavior 就能自动捕获 deleteAll 日志
- 若真需字段级 diff + 操作人,必须自定义 DiffLogBehavior,并且仅用于单条 save/delete 场景
- 批量场景仍需回到 Command + 主动日志的组合方案
补充:确保 user_id 可靠可用
Web 请求中操作人来自 \Yii::$app->user,但要注意:
- 控制台命令中需显式传参或从环境变量/配置读取管理员 ID,不能依赖 session
- API 接口需校验 token 或 header,把解析出的 user_id 存入
\Yii::$app->user或临时上下文 - 日志表若存 user_id 字段,建议建
INDEX(user_id, log_time)加速按人查操作记录


















