插件结构与 info.json 规范

一、插件装在哪里

插件安装后在项目根目录的 plugin/{插件名}/,例如 plugin/sitemap/。类命名空间统一是 plugin\{插件名}\,由内核注册独立的自动加载器,不需要改 composer.json。

二、目录结构

以官方站点地图插件为例:

plugin/sitemap/
├── info.json
├── readme.md
├── controller/
│   ├── Admin.php
│   └── Home.php
└── hook/
    └── ContentHook.php

controller/ 与 hook/ 只是约定,不强制;真正强制的是 info.json 里的类名必须落在 plugin\{name}\ 命名空间下。

三、info.json 必填字段

name  title  type  version  cms_min_version  description  author  is_free

逐条约束:

  • name:小写字母开头,只允许小写字母、数字、下划线,长度 2–64,且必须与目录名完全一致
  • type:只能是 plugin 或 template
  • version / cms_min_version:必须是 x.y.z
  • is_free:必须是布尔值;为 false 时 price 必须大于 0
  • 文件编码:UTF-8 且不能带 BOM,带 BOM 会被直接拒绝

四、hooks 节点

"hooks": [
    {
        "event": "content_after_save",
        "class": "\\plugin\\sitemap\\hook\\ContentHook",
        "method": "afterSave"
    }
]
  • event 必须是系统内置钩子,不允许自定义新增
  • class 必须位于 plugin\{name}\ 下,防止指向系统核心类
  • 三项 event / class / method 缺一不可

五、routes 节点

"routes": [
    {
        "group": "admin",
        "rule": "sitemap/index",
        "class": "\\plugin\\sitemap\\controller\\Admin",
        "action": "index",
        "title": "站点地图",
        "menu": true,
        "parent": "plugin"
    }
]
  • group:admin(后台)或 home(前台)
  • rule:必须以 插件名/ 开头。这条限制从规则上杜绝插件覆盖系统原生路由
  • menu 为 true 时,title 与 parent 必填,用于在后台侧栏生成菜单项

六、其余可选节点

  • depend_plugins:依赖的其他插件名数组,安装时校验
  • database.install_sql / database.uninstall_sql:建表与清理脚本的相对路径,必须是 .sql 结尾
  • config:插件后台配置项,每一项必须包含 title 与 type

七、完整示例

{
    "name": "sitemap",
    "title": "站点地图",
    "type": "plugin",
    "version": "1.0.0",
    "cms_min_version": "1.0.0",
    "description": "自动生成 sitemap.xml,内容保存后标记过期。",
    "author": "LeadoCMS",
    "is_free": true,
    "price": 0,
    "hooks": [
        {
            "event": "content_after_save",
            "class": "\\plugin\\sitemap\\hook\\ContentHook",
            "method": "afterSave"
        }
    ],
    "routes": [
        {
            "group": "admin",
            "rule": "sitemap/index",
            "class": "\\plugin\\sitemap\\controller\\Admin",
            "action": "index",
            "title": "站点地图",
            "menu": true,
            "parent": "plugin"
        }
    ],
    "config": {
        "site_url": {
            "title": "站点域名",
            "type": "text",
            "default": "",
            "tip": "留空则自动取当前请求域名"
        }
    }
}

八、自检清单

  • 目录名 = name 字段
  • 没有 BOM 头
  • 所有类的命名空间都在 plugin\{name}\ 下
  • 路由 rule 以 插件名/ 开头
  • 付费插件填了 price