Skip to Content
扩展与运维插件开发指南

插件系统基于轻量钩子(Hook)机制:插件在 plugins/ 目录下以独立目录形式存在,通过向钩子注册表注册回调来扩展系统能力。

插件结构

plugins/ my-plugin/ plugin.php 插件入口(返回 PluginContract 实例) screenshot.png 插件截图(可选,后台插件卡片缩略图)

截图按目录约定自动发现,文件名为 screenshot.{png|jpg|jpeg|webp|gif|svg}(多种同时存在时按此顺序取第一个)。截图存放在插件目录内(docroot 之外),由 /fy-plugins/{插件名}/screenshot 路由读取并输出(带 ETag/缓存头),无需自行暴露静态资源。

最小示例

<?php use App\Engine\Plugin\HookRegistry; use App\Engine\Plugin\PluginContract; return new class implements PluginContract { public function name(): string { return 'my-plugin'; } public function version(): string { return '1.0.0'; } public function description(): string { return '我的第一个插件'; } public function register(HookRegistry $hooks): void { $hooks->on('fy.head', fn (): string => '<meta name="my-plugin" content="loaded">'); } };

保存后刷新后台「扩展 → 插件」,插件会出现在卡片列表中(含截图缩略图、版本、状态徽标),用右上角开关启用。

可用钩子

钩子类型载荷说明
fy.headrender前台 <head> 注入(统计代码/验证标记)
content.savedactionContent内容保存后触发
  • render 类:回调返回字符串,按优先级拼接后输出
  • action 类:仅执行副作用(日志、通知、同步等)

注册统一使用 $hooks->on(钩子名, 回调)$hooks->render($hook)$hooks->act($hook, ...载荷) 是引擎内部的触发方法,不要在插件里用它们注册。

注册时可指定优先级(数字越小越先执行):

$hooks->on('fy.head', fn (): string => '...', priority: 10);

启用与停用

后台「扩展 → 插件」每张卡片右上角的开关切换启用/停用;停用状态存于 settings,插件的钩子不再注册,但插件文件保留。

  • 插件代码运行在站点进程内,请勿在回调中执行耗时操作(影响前台响应)
  • fy.head 输出会进入所有前台页面的 <head>,请确保 HTML 合法且转义用户数据
  • 插件间通过 name() 保持唯一,避免冲突