api请求统计应挂载在thinkphp中间件中,因其能覆盖所有http入口、支持全局注册、可精准获取路径、方法、状态码、耗时、ip等核心字段,并通过异步队列或批量插入保障性能。

API请求统计该挂在哪里
ThinkPHP 的 API 请求统计,不能只靠控制器里写几行 Db::table('log')->insert() —— 那样漏请求、难维护、还干扰业务逻辑。真正稳定的做法是用中间件(Middleware),它在请求进入路由前、响应返回客户端后都可拦截,天然适合埋点。
中间件能覆盖所有 HTTP 入口(包括 RESTful 接口、带参数的 /api/v1/user/:id、甚至 OPTIONS 预检请求),且支持全局注册或按路由分组启用。
- 新建中间件:
php think make:middleware ApiRequestLogger - 在
app/middleware.php中全局注册(或在路由分组中单独绑定) - 务必在中间件中调用
$next($request),否则请求会卡住 - 不要在中间件里做耗时操作(如直接写文件或同步发 HTTP 请求),优先用异步队列或批量插入
怎么记录关键字段又不拖慢接口
记录太多字段(比如完整 $request->param() 或 $response->getContent())会导致 I/O 延迟飙升,尤其高并发下可能把数据库写挂。实际只需 6–8 个核心字段就够分析:来源、路径、方法、状态码、耗时、IP、UA(可选)、是否登录(可选)。
耗时统计必须用中间件的前后时间差,不能依赖控制器内 microtime(true),否则漏掉前置处理(如 JWT 解析、跨域检查)的时间。
- 记录路径用
$request->url(true)(含 querystring)或$request->rule()->getRule()(仅路由规则,如'api/v1/user/:id') - 状态码要从
$response->getCode()取,不是http_response_code() - 耗时建议用
number_format(microtime(true) - $start, 3),单位秒,保留 3 位小数 - 避免在中间件里查用户信息 —— 如需
user_id,应由前置认证中间件写入$request->withAttr('user_id', ...),本中间件直接读取
数据库表设计和批量写入要点
单条 INSERT 抗不住每秒上百请求,表结构设计和写入方式直接影响稳定性。别用 MyISAM,必须用 InnoDB;别给 url 字段加全文索引,path 和 method 建联合索引更实用。
ThinkPHP 自带的 Db::transaction() 不适合高频日志,推荐用「内存暂存 + 定时刷盘」或「队列异步落库」。简单项目可用静态数组暂存,配合 register_shutdown_function 统一提交(但注意 CLI 模式不触发)。
- 表名建议
api_request_log,字段至少包含:id、path(VARCHAR 255)、method(CHAR 10)、status_code(TINYINT)、cost_time(DECIMAL(6,3))、ip(VARCHAR 45)、create_time(INT UNSIGNED) - 批量插入用
Db::name('api_request_log')->insertAll($dataList),一次最多 500 条,避免 SQL 过长或超时 - 如果用了 Redis 缓存请求计数(比如按
path:method:date统计 QPS),记得设置合理过期时间,避免 key 爆满
如何避免重复记录和漏记
ThinkPHP 的中间件执行顺序、异常中断、以及多级代理(Nginx → PHP-FPM → TP)都会导致统计偏差。最常见的是:404 路由未匹配时不走中间件、异常抛出后 $response 为空、HTTPS 下 $request->ip() 取到的是 Nginx 内网地址。
- 确保中间件注册在
app/middleware.php的'http'数组里,而不是只绑在某个路由分组 —— 否则 404 请求不会进中间件 - 在
try...catch包裹$next($request),即使控制器抛异常,也能拿到$response->getCode()(通常是 500) - 获取真实 IP 要配置
app.request.trust_proxy并设置TRUSTED_PROXY_IPS环境变量,然后用$request->realIP() - 对 OPTIONS 预检请求,可加判断
if ($request->isOptions()) return $response;跳过记录,避免噪音
真正难的不是“怎么记”,而是“什么情况下没记上”。上线前一定要用 curl -X POST -H "Content-Type: application/json" http://localhost/api/xxx 和故意触发 404、500 来验证日志是否全量覆盖。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











