当前位置: 首页 > ds >正文

ThinkPHP的log

文章目录

  • 环境
  • ThinkPHP的log
    • 配置
    • 级别
    • 写log
    • SQL的log
    • request的log
    • response的log
  • 参考

环境

  • Windows 11 专业版
  • XAMPP v3.3.0
  • PHP 8.2.12
  • ThinkPHP v8.1.3

ThinkPHP的log

ThinkPHP的log操作由 \think\Log 类完成,通常我们使用 think\facade\Log 类进行静态调用。

app/controller/Index.php 里添加 test1() 方法如下:

......
use think\facade\Log;
......public function test1() {Log::info('test1');   return 'OK';}

然后curl一下:

curl --silent -XGET "http://localhost:8000/index/test1"

此时,系统就会记录一条log。比如今天是2025年9月1号,在 runtime/log 目录下,会自动创建一个名为 202509 的目录,然后在该目录中创建 01.log 文件,如下:

在这里插入图片描述

配置

ThinkPHP的log配置文件是 config/log.php ,默认如下:

return [// 默认日志记录通道'default'      => 'file',// 日志记录级别'level'        => [],// 日志类型记录的通道 ['error'=>'email',...]'type_channel' => [],// 关闭全局日志写入'close'        => false,// 全局日志处理 支持闭包'processor'    => null,// 日志通道列表'channels'     => ['file' => [// 日志记录方式'type'           => 'File',// 日志保存目录'path'           => '',// 单文件日志写入'single'         => false,// 独立日志级别'apart_level'    => [],// 最大日志文件数量'max_files'      => 0,// 使用JSON格式记录'json'           => false,// 日志处理'processor'      => null,// 关闭通道日志写入'close'          => false,// 日志输出格式化'format'         => '[%s][%s] %s',// 是否实时写入'realtime_write' => false,],// 其它日志通道配置],];

基本上能做到顾名思义,而且默认配置看起来已经比较合理。

补充:如果想要设置单个log文件大小,可以加上 file_size 配置,比如:

            'file_size'      => 10485760, // 10 MB

如果log文件超出了限制,就会另存为一个以时间戳命名的文件。

级别

日志的级别从低到高依次为:

  • debug
  • info
  • notice
  • warning
  • error
  • critical
  • alert
  • emergency

默认的级别是 info

ThinkPHP额外增加了一个 sql 日志级别仅用于记录SQL日志(并且仅当开启数据库调试模式有效,详见下面的介绍)。

注意:系统发生异常后记录的日志级别是 error

app/controller/Index.php 里添加 test2() 方法如下:

    public function test2() {throw new \think\Exception('出错啦!');}

然后访问该方法:

curl --silent -XGET "http://localhost:8000/index/test2"

log记录如下:

[2025-09-01T21:17:57+08:00][error] [0]出错啦!

写log

  • Log::record() :记录日志信息到内存,系统在请求结束后会自动调用 Log::save() 方法统一进行日志信息写入
  • Log::write() :实时写入一条日志信息
  • Log::info() :相当于 Log::write(xxx, 'info') ,其它级别也同理

注意:前面提到,在配置文件 config/log.php 里, realtime_write 可以设置是否实时写入log,事实上该配置只影响 Log::record() ,不影响 Log::write() ,因为后者始终是实时写入的。

日志可以传入一个数组,并且被替换到日志内容中。

例如,在 app/controller/Index.php 里添加 test3() 方法如下::

    public function test3() {Log::info('name: {name}, age: {age}', ['name' => 'Tom', 'age' => 20]);}

然后访问该方法:

curl --silent -XGET "http://localhost:8000/index/test3"

log记录如下:

[2025-09-01T21:26:32+08:00][info] name: Tom, age: 20

SQL的log

查看 config/database.php 的配置,默认如下:

......'trigger_sql'     => env('APP_DEBUG', true),
......

查看 .env 里的 APP_DEBUG 配置:

APP_DEBUG = true

注意:在生产环境中, APP_DEBUG 一般会设置为false。如果希望显示SQL,可以直接把 trigger_sql 设置为true。

测试一下,在 app/controller/Index.php 里添加 test4() 方法如下::

......
use think\facade\Db;......public function test4() {$data = Db::table('t1')->where('c1', '>', 1)->select();return json($data);}

然后访问该方法:

curl --silent -XGET "http://localhost:8000/index/test4"

log记录如下:

[2025-09-01T21:44:36+08:00][sql] SELECT * FROM `t1` WHERE  `c1` > 1 [ RunTime:0.000520s ]

request的log

如果能把ThinkPHP收到的request也记到log里,一来可以确认ThinkPHP是否收到了request,二来可以查看request的详细信息,帮助debug问题。

不过,貌似没有简单的配置可以记录request log,可以通过中间件(middleware)来完成。

首先创建中间件,可以用命令行操作(在项目根目录下):

php think make:middleware RequestLog

操作完成后,会在 app/middleware 目录下创建 RequestLog.php 文件如下:

<?php
declare (strict_types = 1);namespace app\middleware;class RequestLog
{/*** 处理请求** @param \think\Request $request* @param \Closure       $next* @return Response*/public function handle($request, \Closure $next){}
}

修改 handle() 方法如下:

......
use think\facade\Log;
......public function handle($request, \Closure $next){// 记录请求信息$logData = ['ip' => $request->ip(),'method' => $request->method(),'url' => $request->url(),'params' => $request->param(),'header' => $request->header(),'user_agent' => $request->header('user-agent'),'time' => date('Y-m-d H:i:s')];Log::info('Request Received: ' . json_encode($logData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));return $next($request);}
}

可以根据需求,记录各种详细信息,注意可能会有一些敏感信息。

注意:如果担心中间件出问题影响后续操作,可以用 try...catch 包起来,这样即使记录log时出了问题,也不会影响对request的后续操作。

然后在 app/middleware.php 里注册中间件:

return [......\app\middleware\RequestLog::class,
];

现在,ThinkPHP就会把收到的request记录到log里,比如:

[2025-09-02T10:34:45+08:00][info] Request Received: {"ip": "111.201.72.246","method": "GET","url": "\/api\/index.php\/login\/checkLogin","params": [],"header": {"priority": "u=4","cookie": "PHPSESSID=0f117871cf16d58cf74f63cbba71963d","connection": "keep-alive","referer": "http:\/\/chinatt.org.cn\/","accept-encoding": "gzip, deflate","accept-language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2","accept": "*\/*","user-agent": "Mozilla\/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko\/20100101 Firefox\/142.0","host": "chinatt.org.cn"},"user_agent": "Mozilla\/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko\/20100101 Firefox\/142.0","time": "2025-09-02 10:34:45"
}

response的log

既然可以在处理request前记录request的log,那么同理,也可以在生成response后记录response的log。

修改 RequestLog.php 如下:

    public function handle($request, \Closure $next){// 记录请求信息$logData = ['ip' => $request->ip(),'method' => $request->method(),'url' => $request->url(),'params' => $request->param(),'header' => $request->header(),'user_agent' => $request->header('user-agent'),'time' => date('Y-m-d H:i:s')];Log::info('Request Received: ' . json_encode($logData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));$response = $next($request);// 记录响应信息$logData = ['code' => $response->getCode(),'header' => $response->getHeader(),'content' => $response->getContent(),'time' => date('Y-m-d H:i:s')];Log::info('Response Sent: '. json_encode($logData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));return $response;}

可根据需求决定要记录哪些详细信息。另外,response有可能非常大,可能需要截取其中一部分。

参考

  • https://doc.thinkphp.cn/v8_0/log.html
http://www.xdnf.cn/news/19907.html

相关文章:

  • C++二维数组的前缀和
  • 小杰机械视觉(finally)——题库上——gray、thresh、erode、dilate、HSV、开运算、ROI切割、矫正。
  • 博主必备神器~
  • HBase Region
  • 【代码解读】Deepseek_vl2中具体代码调用
  • 一款高效、强大的子域名爬取工具,帮助安全研究者和渗透测试人员快速收集目标域名的子域名信息
  • 服务器数据恢复—OceanStor存储数据丢失原来这样恢复
  • HOW - 在浏览器下载一个 Excel 表格文件
  • 基于SpringBoot的大学生就业招聘系统
  • 撤回通知(我自己的账号)
  • 自建局域网gitlab如何修改提交时间
  • 不做推销做共情:一个小众独立站靠宠物殡葬用品,年营收超3600万元
  • 机器学习笔记-第二周
  • 力扣:2458. 移除子树后的二叉树高度(dfs序)
  • 基于单片机车流车速检测系统设计
  • C++字符串操作:string类与数组对比
  • MySQL知识大全
  • ansible循环+判断(with,loop,when,if,for)
  • Python爬虫进阶:面向对象编程构建可维护的爬虫系统
  • Babylon 编辑器快捷键小记
  • 零构建的快感!dagger.js 与 React Hooks 实现对比,谁更优雅?
  • Python OpenCV图像处理与深度学习:Python OpenCV DNN模块深度学习与图像处理
  • 线程安全问题及解决方案
  • 163起融资,梅卡曼德融资额夺冠,钉钉、百度智能云10周年,汉桑科技IPO| 2025年8月人工智能投融资观察 · 极新月报
  • Android --- 搭建JNI框架
  • % g++ *.cpp ...: fatal error: ‘opencv2/opencv.hpp‘ file not found 1
  • 数论常见公式定理大全
  • 无需服务器,免费、快捷的一键部署前端 vue React代码--PinMe
  • 嵌入式学习 51单片机基础
  • 《微服务协作实战指南:构建全链路稳健性的防御体系》