Z-Blog 插件启用后整站打不开:Filter_Plugin 钩子写错的典型三种姿势

· zblog · 阅读 15
摘要

启用插件后整个站变成白屏或者 500,后台也进不去——这是 Z-Blog 插件开发最常见的翻车现场。九成以上不是 Z-Blog 的问题,而是 Filter_Plugin 系列钩子里有一处写错,导致每次请求都在同一个地方炸掉。 为什么插件一

启用插件后整个站变成白屏或者 500,后台也进不去——这是 Z-Blog 插件开发最常见的翻车现场。九成以上不是 Z-Blog 的问题,而是 Filter_Plugin 系列钩子里有一处写错,导致每次请求都在同一个地方炸掉。

为什么插件一挂全站就死

Z-Blog 的 Filter 钩子是在「每次请求」都会执行的路径上挂载的。你在 ActivePlugin_你的插件名() 里 Add_Filter_Plugin('Filter_Plugin_Index_Begin', 'MyFunc'),之后每一次首页请求都会调用 MyFunc。只要这个函数本身有语法错误、调用了不存在的类、或者抛了未捕获的异常,首页就 500,而这个钩子挂载动作在 c_option.php 加载的插件列表阶段就已经完成,所以你连后台都进不去。

三种典型写错姿势

姿势一:回调函数里用了不存在的方法

最常见。比如写 $zbp->GetArticleList()——Z-Blog 里正确的方法是 $zbp->GetPostList() 或者直接用 GetList() 类。PHP 7+ 遇到调用不存在的静态/实例方法会抛 Error,而这个 Error 在钩子链里没有被捕获,直接冒泡成 500。

排查:开 ZC_DEBUG_MODE,或者去 zb_users/logs/ 看最新日志,通常会写明 Call to undefined method。

姿势二:include 了插件自己目录下不存在的文件

插件 include.php 里 require 一个 lib/xxx.php,但实际文件名大小写不一致。Linux 服务器区分大小写,Windows 不区分——本地没事,传上去就炸。表现是 Failed opening required。

排查:ls zb_users/plugin/你的插件/ 逐个核对文件名大小写,尤其注意 Include.php 和 include.php 的区别。

姿势三:在 Filter_Plugin_Zbp_Load 里没有跳过系统与插件目录

这个钩子会在每次加载类文件时触发。如果你在里面无条件 require_once 或者 str_replace 路径,很容易把 zb_system/ 或 zb_users/plugin/ 下的核心类文件也改写掉,导致核心类加载失败——这种是最致命的,因为后台自己也进不去。

正确写法必须显式排除:

function MyPlugin_Zbp_Load(&$classname) {
    if (strpos($classname, 'zb_system') !== false) return;
    if (strpos($classname, 'zb_users/plugin') !== false) return;
    // 你的逻辑
}

出了事怎么救回来

  1. 把站点目录里 zb_users/plugin/你的插件/ 整个改名或移走——Z-Blog 加载不到就自动跳过,站立刻恢复。
  2. 或者直接改数据库 zbp_config 表里 ZC_USING_PLUGIN_LIST 这个字段,把这个插件名删掉。
  3. 恢复后在本地复现,先只挂一个空钩子跑通,再逐步加逻辑。

FAQ

Q:插件启用后只是前台白屏、后台正常?
A:说明钩子挂在模板类而不是加载类上,通常是 Filter_Plugin_Index_Begin 或 Filter_Plugin_ViewArticle_Begin 里的代码报错。后台能进就说明系统加载链没被打断。

Q:改 c_option.php 删插件行不行?
A:可以,但 c_option.php 是单文件配置,直接改容易把格式改坏。更安全的是用后台「插件」页面禁用,或者改数据库 zbp_config。

Q:有没有办法让插件报错不拖垮全站?
A:可以在插件入口函数最外层包 try...catch,捕获后 return 而不是继续抛。但这只是止血,根源还是要把钩子逻辑写对。