开发指南
应用开发规范
应用是四端齐备的独立业务系统:后端模块、站点后台页面、C 端分包、DIY 装修组件。本章定义应用包结构、生命周期钩子与四端约定——照此开发的应用可以被商店分发、免编译安装、无残留卸载。
从脚手架开始
$ php webman ext:keygen # 生成 Ed25519 签名密钥对(一次)
$ php webman ext:create # 脚手架一个可打包安装的应用骨架
$ php webman ext:gen # 从表结构 JSON 生成实体 CRUD(迁移/模型/控制器/路由/菜单/管理页)
$ php webman ext:pack # 签名并打包为 .tzapp / .tzaddon
应用包结构
应用以 .tzapp(zip)分发。以官方商城为例,包内结构:
├── info.json # 应用元信息(见下)
├── features.json # FeatureGate 功能开关贡献
├── trade.json # 业务交易类型声明(接入统一收银台)
├── menu.json # 菜单/权限点树 + member_entries(可选)
├── signature.json # Ed25519 逐文件 sha256 + 总签名
├── server/ # PHP 后端(PSR-4: apps\shop\)
│ ├── App.php # 生命周期入口
│ ├── route.php hooks.php schedules.php
│ ├── controller/{admin,api}/ model/ service/ job/
│ ├── trade/OrderHandler.php # 交易回调
│ ├── search/ export/ poster/ workbench/ # 横向能力实现类
│ └── migrations/{install,upgrade}/V20260715__create_tables.sql
├── admin/ # 免编译 ESM 管理页
│ ├── routes.json # 路由/菜单/权限声明
│ └── goods.mjs orders.mjs ...
├── diy/components.json # 装修组件 schema 声明
├── search/providers.json # 全局搜索域贡献
├── export/sources.json # 导出数据源贡献
├── poster/scenes.json # 海报场景贡献
└── workbench/todos.json # 工作台待办贡献
{
"key": "shop", // ^[a-z][a-z0-9_]{1,40}$,保留字(core/admin/api...)不可用
"type": "app", // app | addon
"name": "商城",
"version": "1.0.0", // x.y 或 x.y.z 纯数字
"min_framework": ">=0.2.0", // 框架版本约束
"uninstall_keep_data": true,
"tables": ["shop_goods", "shop_order", ...] // 本应用建表清单(卸载处理依据)
}
生命周期
包内 server/App.php(namespace apps\{key})实现生命周期接口。部署级(代码装到服务器)与站点级(业务对某站点开通)严格区分:
install(): void // 部署级安装(DDL 已由迁移完成,只做数据初始化)
upgrade(string $from, string $to) // 部署级升级,逐版链式调用
uninstall(bool $keepData) // 卸载,删文件前执行
onEnable() / onDisable() // 部署级启停
onSiteBind(int $siteId) // 站点绑定:初始化站点默认配置(须幂等)
onSiteUnbind(int $siteId, bool $purgeData) // 站点解绑
- DDL 一律走迁移:
server/migrations/install/(全新安装)与upgrade/(版本增量链),文件名V<时间戳>__描述.sql,必须幂等、过db:lint双版本红线。生命周期钩子里只做数据初始化 / 清理,框架不包事务,钩子自负幂等。 - 安装编排由框架完成:解包 → 验签 → 解析 → 预检 → 备份后落盘 → 迁移 → 注册物挂载 → 快照登记 →
App::install()→ 平滑加载。任一步失败物理回滚(只 DROP 本次新建的表),进程中断可用ext:resume恢复。 - 卸载:有站点仍绑定或有插件依赖时禁止;按
uninstall_keep_data保留(登记孤儿表清单)或删除业务表;全部注册物自动回收,卸载零残留由注册台账机制保证。
四端约定
| 端 | 约定 |
|---|---|
| 后端 | 命名空间 apps\{key}\;路由自动前缀:C 端 /api/app/{key}/...、站点后台 /adminapi/app/{key}/...;业务表前缀 {{prefix}}{key}_(在 info.json.tables 登记);模型强制 SiteScoped |
| 管理端 | admin/ 下的 ESM 产物 + routes.json 声明,装完刷新即用;开发规范见 Admin SDK |
| C 端 | uniapp/src/apps/{key}/ 工作区,编译后即分包;分包之间禁止相互 import,公共能力(@/api、@/utils、@/components)一律来自主包 |
| DIY 组件 | 服务端 schema 声明(diy/components.json)+ C 端组件(uniapp/src/apps/{key}/diy/ + manifest.json),构建前生成器自动把组件登记进主包渲染器 |
横向能力:声明即接入
内核的横向中台全部开放给应用,一份声明文件 + 一个实现类即接入,卸载自动回收:
| 能力 | 声明文件 | 实现契约 |
|---|---|---|
| 统一收银台 | trade.json | TradeHandlerInterface(onPaid / onRefunded / onClosed) |
| 全局搜索域 | search/providers.json | SearchProviderInterface |
| 导出数据源 | export/sources.json | ExportSourceInterface |
| 分享海报场景 | poster/scenes.json | PosterSceneInterface |
| 工作台待办 | workbench/todos.json | TodoProviderInterface |
| 功能开关 | features.json | 键必须以 {key}. 前缀(如 shop.enabled) |
| 定时任务 | server/schedules.php | 任务类 |
| 事件订阅 | server/hooks.php | 监听器类,见扩展点手册 |
多应用共存的 UI 组织
- 1业务流程页自带默认 UI:商品详情、下单等由应用定稿,不开放装修。
- 2聚合页交给站点装修:首页 DIY 混排各应用组件;tabBar 全量装修数据驱动;「我的」页经
menu.json的member_entries注册入口。应用应声明默认推荐区块,保证绑定即有可跑首页。 - 3主题 token 统一视觉:全部页面强制消费站点主题 token(红线)——站点改主色,所有应用同步生效。