内置钩子、插件路由与打包上架

一、七个内置钩子

插件只能挂载以下事件,这是内核白名单,不允许扩充:

  • app_init 应用初始化,适合做全局前置动作
  • admin_menu_render 后台菜单渲染,可以向侧栏插入菜单
  • content_before_save 内容保存之前,适合做校验与拦截
  • content_after_save 内容保存完成,适合做同步、通知、缓存刷新
  • view_before_render 页面渲染前,可以修改模板上下文
  • view_after_render 页面渲染完成,可以改写最终 HTML
  • upload_after 文件上传完成,适合做压缩、水印、转存

其中 admin_menu_render 属于「过滤型钩子」,有返回值且需要链式传递参数;其余钩子只做通知,返回值会被忽略。

二、钩子方法怎么写

namespace plugin\sitemap\hook;

class ContentHook
{
    public function afterSave(array $context): void
    {
        // 内容保存后标记 sitemap 过期,下次访问时惰性重建
    }
}

约定:方法接收一个上下文数组,过滤型钩子返回修改后的值,通知型钩子返回空即可。

三、插件路由怎么生效

info.json 里声明的路由会在插件启用时注册:

  • group=admin → 后台路由,路径形如 /admin/{rule}
  • group=home → 前台路由,路径形如 /{rule}

因为是显式注册而不是扫描目录,所以插件停用后路由立即消失,不会留下可访问的入口。

四、插件配置怎么读

info.json 的 config 节点定义的是表单项,用户在后台填写后存库。插件代码里读配置即可,不需要自己建表。

五、打包规则

上传的是 zip 包,内核会做以下限制(数值来自内核配置):

  • 压缩包 ≤ 20 MB
  • 解压后总体积 ≤ 200 MB
  • 包内文件条目 ≤ 2000
  • 压缩比 ≤ 100(防止 ZIP 炸弹)

超出任意一条都会被拒绝,并给出明确原因。

六、打包步骤

  1. 确认目录名与 name 一致
  2. 确认 info.json 是 UTF-8 无 BOM
  3. 在插件目录内部全选文件打包(不要连外层目录一起打,否则解压后多一层)
  4. 上传后在后台插件列表查看状态

七、上架到市场

市场分发需要中台侧的商品记录与 AppKey 校验:

  1. 在中台创建商品,填写插件名、版本、价格与说明
  2. 后台配置市场地址与 AppKey(.env 的 [MARKET] 段)
  3. 上传 zip 包,由中台完成审核与上架
插件安装到站点后,域名授权由中台校验;本地开发环境可用测试密钥联调。

八、调试建议

  • 先在本地把 debug 打开,确认钩子确实被调用
  • 插件出问题先停用,确认站点恢复正常,再逐个钩子排查
  • 不要在主流程里做网络请求,插件异常不应该拖垮内容保存