插件系统基于轻量钩子(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.head | render | 无 | 前台 <head> 注入(统计代码/验证标记) |
content.saved | action | Content | 内容保存后触发 |
- render 类:回调返回字符串,按优先级拼接后输出
- action 类:仅执行副作用(日志、通知、同步等)
注册统一使用 $hooks->on(钩子名, 回调);$hooks->render($hook) 与 $hooks->act($hook, ...载荷) 是引擎内部的触发方法,不要在插件里用它们注册。
注册时可指定优先级(数字越小越先执行):
$hooks->on('fy.head', fn (): string => '...', priority: 10);启用与停用
后台「扩展 → 插件」每张卡片右上角的开关切换启用/停用;停用状态存于 settings,插件的钩子不再注册,但插件文件保留。
- 插件代码运行在站点进程内,请勿在回调中执行耗时操作(影响前台响应)
fy.head输出会进入所有前台页面的<head>,请确保 HTML 合法且转义用户数据- 插件间通过
name()保持唯一,避免冲突