TanzCMS开源CMS系统

模块开发手册

一方业务模块的目录结构、清单、路由、迁移、资源和命令规范。

更新:2026-05-31 02:42:50 浏览:4

模块开发手册

模块用于承载 TanzCMS 一方业务域,例如内容、会员、订单、支付、官方文档。模块不是插件,不用于承载第三方可选能力。

目录结构

modules/{code}/
├─ composer.json
├─ manifest.json
├─ src/
│  ├─ {Code}ServiceProvider.php
│  └─ Http/Controllers/
├─ routes/
│  ├─ web.php
│  ├─ admin.php
│  └─ api.php
├─ database/migrations/
├─ resources/views/
├─ resources/lang/zh_CN/
└─ resources/assets/

模块公开资源发布到:

public/assets/modules/{code}/

模块前台模板默认放到:

themes/default/modules/{code}/

manifest.json

manifest.json 保存模块元数据、路由入口、依赖、表声明、菜单、会员菜单、模板标签和命令声明。

示例:

{
  "code": "docs",
  "name": "官方文档",
  "version": "1.0.0",
  "type": "module",
  "providers": [
    "Modules\\Docs\\DocsServiceProvider"
  ],
  "routes": {
    "web": "routes/web.php",
    "admin": "routes/admin.php",
    "api": "routes/api.php"
  },
  "requires": {
    "tanzcms": "^1.2"
  },
  "tables": [
    "doc_books",
    "doc_pages"
  ],
  "console_commands": [
    "tanzcms:docs-import"
  ]
}

manifest.json 不是 ServiceProvider 的替代品。路由、视图、迁移、语言包和资源加载仍由模块 ServiceProvider 负责。

ServiceProvider

模块 ServiceProvider 应负责:

  • 注册服务和绑定。
  • 加载模块路由。
  • 加载视图、迁移、语言包。
  • 注册模板标签、菜单上下文或事件监听。
  • 注册控制台命令。

需要会话、CSRF 或后台鉴权的路由必须放在 web 中间件边界内。

路由边界

文件 用途
routes/web.php 模块前台页面
routes/admin.php 模块后台页面和后台接口
routes/api.php 模块 API 或回调扩展

模块路由不要注册全站级 catch-all,避免抢占栏目、内容详情、主题资源和前台 fallback。

数据库迁移

模块新增表迁移放在:

modules/{code}/database/migrations/

表名通过系统表前缀规则解析,代码中不要到处手写物理表名。模块安装、升级和测试时应验证迁移能在空库和已有站点中稳定执行。

后台菜单和权限

模块菜单可以在 manifest 中声明。后台接口还必须配置页面权限和功能权限。

权限建议按模块分组:

module.{code}.page
module.{code}.page.create
module.{code}.page.update
module.{code}.page.delete

前端隐藏按钮只负责体验,后端接口必须再次校验权限。

资源发布

模块后台 CSS/JS 放在 resources/assets,安装或访问模块后台页面时发布到:

public/assets/modules/{code}

发布目录只作为静态资源输出,不作为源码维护入口。

控制台命令

模块命令应声明在 console_commands 中。系统会在执行对应 Artisan 命令时按需启动模块,避免把模块命令硬编码进核心入口。

{
  "console_commands": [
    "tanzcms:docs-export",
    "tanzcms:docs-import"
  ]
}

初始数据

模块如需内置初始数据,应提供可重复导入的 JSON、Seeder 或命令,并按稳定业务键更新,例如 slugcodekey,不要依赖本地数据库 ID。

导入策略应给管理员选择:

  • 空库导入。
  • 按稳定键更新已有数据。
  • 清空后重新导入。
  • 跳过导入。