TP5函数文件不支持自动监控,需用Hook在app_begin和app_end埋点;common.php中无法获取执行上下文和耗时数据,因框架未初始化且无响应钩子时机。

TP5 的函数文件本身不支持自动监控,必须靠手动埋点 + 行为钩子(Hook)或中间件实现,否则根本拿不到执行上下文和耗时数据。
为什么不能直接在 common.php 里加监控逻辑?
ThinkPHP5 的 common.php 是全局加载的函数文件,所有请求都会执行它——但此时框架尚未初始化, hinkApp、 hinkRequest 等核心对象都不可用。你没法知道当前是哪个控制器、哪个方法、走了哪条路由,更没法记录耗时起点。
- 试图在
common.php中调用microtime(true)记录开始时间,但没地方配对调用microtime(true)算差值 -
common.php里无法访问$this或请求实例,也拿不到响应前的钩子时机 - 即使硬写日志,也会混入框架初始化、配置加载等非业务耗时,干扰判断
正确做法:用 Hook 在 app_begin 和 app_end 埋点
TP5 的行为扩展机制提供了 app_begin 和 app_end 两个稳定钩子,分别在应用启动后、响应发送前触发,正好构成完整生命周期闭环。
- 在模块的
tags.php中注册行为:return [ 'app_begin' => ['app\common\behavior\MonitorBegin'], 'app_end' => ['app\common\behavior\MonitorEnd'], ]; -
MonitorBegin类中用静态变量存起始时间:public function run(&$params) { hinkCache::tag('monitor')->set('start_time', microtime(true)); } -
MonitorEnd类中读取并记录:public function run(&$params) { $start = hinkCache::tag('monitor')->get('start_time'); if ($start) { $cost = round((microtime(true) - $start) * 1000, 2); // 写入日志或上报 hinkLog::record("Request cost: {$cost}ms", 'info'); } } - 注意:不要用
session或$_SESSION存起始时间——TP5 默认不开启 session,且多线程/FPM 下不安全
想监控具体函数调用?别改函数文件,改调用方
TP5 没有类似 Laravel 的服务容器自动代理机制,common.php 里定义的函数(比如 get_client_ip())被调用时,框架完全无感知。想监控它们,只能在调用处手动包一层:
- 在控制器或模型中,不直接写
get_client_ip(),而是:$ip = hinkHook::listen('before_get_client_ip', $_SERVER); if (empty($ip)) { $ip = get_client_ip(); hinkHook::listen('after_get_client_ip', $ip); } - 然后在
tags.php中绑定对应钩子行为,做计时或日志 - 或者更简单:用装饰器思路封装函数,例如
monitored_get_client_ip(),内部调用原函数并打点 - 避免给每个函数都加监控——优先盯住高频、I/O 密集、或已知慢的函数,比如数据库查询包装、远程 HTTP 调用封装
容易被忽略的关键点
Hook 行为类里的 run() 方法接收的是引用参数 &$params,但这个参数内容由触发方决定:app_begin 的 $params 是空数组,action_begin 才带控制器/方法名。别指望所有钩子都能拿到完整上下文;真正要定位到「哪个方法慢」,必须结合 Xdebug 或 XHProf 这类底层分析工具,函数文件层的埋点只适合粗粒度看整体或关键节点。

















