ThinkPHP6模型中写入自定义日志的核心是利用模型事件钩子(如afterInsert、afterUpdate、afterDelete)或手动调用Log门面,在关键操作节点记录结构化日志;可配置独立日志通道,避免与框架日志混杂。

在 ThinkPHP6 模型中写入自定义日志,核心是利用模型的事件钩子(如 afterInsert、afterUpdate、beforeDelete 等)或手动调用日志服务,在关键操作节点记录行为。不依赖第三方扩展,TP6 自带的日志驱动已足够灵活。
使用模型事件自动记录日志
ThinkPHP6 的模型支持生命周期事件,可在数据变更前后插入日志逻辑。需确保模型启用了事件支持(默认开启),并在模型类中定义对应方法:
- 在模型类中定义
afterInsert方法,记录新增日志 - 定义
afterUpdate方法,记录编辑日志 - 定义
afterDelete方法,记录删除日志
示例(以 User 模型为例):
namespace app\model;
use think\Model;
use think\facade\Log;
class User extends Model
{
// 新增后写入日志
public function afterInsert()
{
Log::info('用户创建', [
'user_id' => $this->id,
'username' => $this->username,
'ip' => request()->ip(),
'time' => date('Y-m-d H:i:s')
]);
}
// 更新后写入日志
public function afterUpdate()
{
Log::info('用户资料更新', [
'user_id' => $this->id,
'update_fields' => $this->getChangedData(),
'ip' => request()->ip()
]);
}
}
手动在业务逻辑中调用日志服务
当需要更精细控制(如仅在特定条件、特定字段变更时记录),可在控制器或服务层中显式调用 think\facade\Log:
立即学习“PHP免费学习笔记(深入)”;
- 使用
Log::info()、Log::notice()、Log::error()区分日志级别 - 日志内容建议结构化(数组),便于后续解析或对接 ELK 等系统
- 可结合
trace()或debug_backtrace()记录调用栈(慎用,避免性能损耗)
示例:
use think\facade\Log;
public function updateProfile()
{
$user = User::find(input('id'));
if ($user && $user->save(['nickname' => input('nickname')])) {
Log::notice('用户昵称修改成功', [
'user_id' => $user->id,
'old_nickname' => $user->getOrigin('nickname'),
'new_nickname' => input('nickname'),
'operator' => session('admin_id') ?: 'unknown'
]);
return success();
}
Log::error('用户昵称修改失败', ['input' => input()]);
return fail();
}
为日志指定独立通道和配置
避免自定义日志混入框架默认日志,可在 config/log.php 中新增通道,例如:
'channels' => [
'custom' => [
'type' => 'File',
'path' => __DIR__ . '/../runtime/log/custom/',
'level' => 'info',
'file_size' => 2097152, // 2MB
'backup_num' => 10,
'format' => '[%s][%s] %s %s',
],
],
然后在模型或控制器中使用该通道:
Log::channel('custom')->info('业务操作', [...]);
记录数据库原始 SQL(调试用)
若需追踪模型操作对应的 SQL,可启用查询日志并单独输出:
- 临时开启:在模型方法开头加
Db::startTrans(); Db::getLastSql();不适用;应改用监听器或中间件 - 推荐方式:在
app/common.php或中间件中监听think\db\Query事件,捕获QueryBefore和QueryAfter - 简单调试:在模型事件中用
$this->getLastSql()(仅限当前查询,且需开启调试模式)
注意:生产环境避免长期记录完整 SQL,尤其含敏感参数时需脱敏处理。



















