links 机制有必要存在吗
结论先行:有必要,但必要性不在性能。如果只看 opcache 命中后的 CPU,这个机制的性价比确实很弱;它存在的理由应该是下面几条。
一、它真正买到的东西
- “加一条链接”不再等于“执行一个插件的 PHP”。
dev_docs只加一条“开发者”,旧方案却让每个前台页面 include 12.9 KB、声明 8 个函数。现在这个文件完全不进前台请求。哪怕 opcache 命中,也少了函数表、manifest 数组构造和插件代码路径。- 入口渲染有了确定的失败边界。
旧路径是
hook() → plugin_call() → include → 回调,回调抛异常会停用插件并把整页打成 500。links 路径不执行插件代码,菜单不会因为某个插件写错而挂掉。这是故障隔离,和 opcache 无关。- 入口输出从“各写各的”变成统一校验。
URL 只允许相对地址或 http/https、
icon_html只允许绘图标签、文案统一转义、参数键白名单、每入口最多 20 条。非法条目在同步时就被丢弃。注意:这不是防恶意插件(插件本来就有完整 PHP 权限),而是防作者手误——漏h()、拼出javascript:、把未过滤的配置值塞进菜单。- 入口成为可检查、可配置的数据。
when.login/admin/self/config/ctx、Tab 的key/before/after、text_config都由核心统一处理;插件不再重复写“登录才显示”“管理员才显示”,后台改个配置就能改入口文案。二、哪里值得用,哪里是边际收益
场景 links 的价值 入口是插件在该页面的唯一职责( dev_docs前台)高:整份插件代码退出请求路径 入口回调里有数据库计算/资源加载( user_level个人卡片 61 µs)高:实测每页省 ~57 µs 插件本来就因别的 Hook 加载,回调只是 $links[] = ...(points_mall、color_scheme等)低:只剩统一校验和错误隔离,性能几乎为零 入口需要动态徽章、动态文案、拼接 HTML、 plugin_asset_require()不适用:必须继续用 Hook 所以“所有入口都迁 links”没有必要;按上面的阈值迁移才有意义。
三、它最大的代价,不是内核代码
内核侧成本很小(
Plugin.php约 186 行 +index.php20 行),真正贵的是双份维护:- 为了兼容老内核,旧回调必须保留;
- 新内核声明
links后回调整段跳过,回调变成死代码; - 插件文件体积不减小,两份定义语义还必须手工保持一致。
如果哪天确定不再兼容老内核,把这些回调删掉,links 才会变成单一事实来源,这个机制才真正“干净”。在此之前,双份定义是它的主要成本。
四、结论与建议
- 保留,但别把它当性能优化宣传。 它的定位是“入口的数据化 + 统一校验 + 故障隔离”,性能只是顺带。
- 不要为了链接而链接。 插件已经会加载、回调只是一行 append 的,迁移收益主要是代码规范,可选;入口是插件唯一前台职责、或回调里有 DB 计算的,优先迁。
- 动态入口永远留给 Hook。 不要为了“全部数据化”把徽章、计数、资源加载硬塞进 links。
- 中期收益点: 如果能放弃老内核兼容,删掉保留的入口回调——那时 links 的必要性会明显高于现在。
一句话:如果这个站没有插件市场、只有你自己写插件,links 基本没必要;既然有第三方插件和统一入口的诉求,它值得存在,但要按上面的边界使用,而不是全量迁移。
主楼