生命周期挂载与调试:从“不生效”到“秒定位”的实战笔记
写插件或者魔改功能的时候,最常遇到的一个问题就是:“我明明写了 hook,怎么就是不跑?” 尤其是刚接触 Xiuno 的朋友,十有八九在生命周期上栽过跟头。今天不聊大道理,就讲我实际踩过的三个坑,以及我现在是怎么挂、怎么查的。
先说我自己的挂载习惯。很多人喜欢把所有 hook 都堆在 install 里,图省事。但一旦插件更新,install 不会重跑,你新增的 hook 就永远不生效。我现在统一用 plugin_xxx_hook.php 这个入口文件来挂,它每次加载都会执行,比 install 可靠得多。比如我想在帖子查看页加一段逻辑,就在这个文件里写:
hook::add('post_view', function($post) {
// 你的逻辑
});
注意,这里的 post_view 是 Xiuno 内置的一个 hook 点,不是你自己定义的函数名。很多人搞混,以为 hook::add 的第一个参数是回调函数名,其实它是“事件名”。事件名写错了,代码再对也不跑。
第二个坑是调试。我早期写生命周期逻辑,全靠 echo 和 var_dump,然后刷新页面看输出。但有些 hook 是在 AJAX 请求或者 CLI 下触发的,你根本看不到输出。后来我改用写日志的方式:
file_put_contents(APP_PATH.'tmp/debug.log', date('Y-m-d H:i:s').' - '.json_encode($data).PHP_EOL, FILE_APPEND);
这个路径是 Xiuno 默认的 tmp 目录,权限没问题的话,所有调试信息都会落在这里。比 echo 强在:不干扰页面输出,而且能记录多次触发的顺序。我遇到过一种情况,一个 hook 被触发了两次,页面显示正常但数据重复,就是靠日志的调用时间戳才定位到的。
第三个想说的是“断点式调试”。如果你用的是 VS Code 或者 PhpStorm,可以配 Xdebug 打断点。但 Xiuno 的 hook 回调是闭包函数,断点有时候不生效。我的替代方案是:在回调函数第一行写一个 if(defined('DEBUG_HOOK')) 判断,然后配合环境变量开关。这样生产环境不干扰,开发环境随时能看到调用栈。
最后给一个排查流程,按顺序做,基本能解决 90% 的“生命周期不生效”:
1. 确认 hook 点名字拼写正确,去 index/control/ 对应控制器里搜一下这个事件名,看它到底在哪个方法里触发。
2. 确认你的插件在后台是“启用”状态,且 hook 文件被 include 了——可以在 hook 文件顶部写个日志,看它有没有被加载。
3. 确认回调函数没有语法错误,用 php -l 检查。
4. 如果以上都对,那就是触发条件的问题,比如某个 hook 只在特定用户组或特定路由下才触发,去读一下源码里的 if 条件。
生命周期这东西,说白了就是“在正确的时间点做正确的事”。挂错了不报错,但就是不干活,最容易让人抓狂。希望这篇能帮你少走点弯路。