Skip to content

按数据表开发业务(实战)

从一张空表到管理后台里可用的功能页面,完整走一遍。本文用「商品品牌管理」作为例子(表 brands,模块 brand),你可以照着换成自己的业务表。

前置:已按 MCP 开发助手 完成客户端接入,并执行过一次 init_client_assets。没有 MCP 也能按本文做,只是每一步都要自己动手,AI 帮不上忙。

先记住分工,这决定了成品质量

基础 CRUD 由生成器出,业务逻辑由 AI 加。 框架规范明确要求:基础增删改查必须先用 php think make:crud 生成骨架,AI 只在骨架之上做增量(审核流转、状态机、批量操作、跨表编排)。让 AI 从零手写整套 CRUD 是错误姿势——它绕过了生成器已经保证正确的分层、命名、路由和前端联动,反而更容易出错。

1. 设计并创建数据表

字段命名遵循框架约定(详见业务模块规范 第 2 章):时间戳固定 created_at / updated_at / deleted_at,状态字段固定 status1 启用 / 0 禁用)。

sql
CREATE TABLE `brands` (
  `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '品牌ID',
  `name` varchar(64) NOT NULL DEFAULT '' COMMENT '品牌名称',
  `logo` varchar(255) NOT NULL DEFAULT '' COMMENT '品牌LOGO',
  `initial` char(1) NOT NULL DEFAULT '' COMMENT '首字母',
  `website` varchar(255) NOT NULL DEFAULT '' COMMENT '官网地址',
  `description` varchar(500) NOT NULL DEFAULT '' COMMENT '品牌简介',
  `sort` int NOT NULL DEFAULT '0' COMMENT '排序,越大越靠前',
  `status` tinyint NOT NULL DEFAULT '1' COMMENT '状态:1启用 0禁用',
  `created_at` datetime DEFAULT NULL COMMENT '创建时间',
  `updated_at` datetime DEFAULT NULL COMMENT '更新时间',
  `deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
  PRIMARY KEY (`id`),
  KEY `idx_status_sort` (`status`, `sort`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品品牌表';

字段注释直接决定生成质量

COMMENT 不是写给人看的装饰。make:crud 的类型推断、表单控件映射、搜索条件判定全部读取真实表结构和注释;AI 也靠注释理解字段语义。注释缺失时,生成器只能按类型兜底成普通输入框,AI 则只能靠字段名猜——initial 这种字段没有注释,谁都不知道它是「首字母」。

建完表后同步写入 server/public/install/data/schema.sql,否则全新安装会缺表。

2. 让 AI 先认识这张表

打开 Cursor / Kimi Code / Claude Code,直接说:

text
看一下 brands 表结构,说说这个模块该怎么建

助手会调用 show_table_schema 读出真实字段,再结合 get_conventions 的框架规范给出方案。这一步的价值是校对:如果它复述的字段和你的设计有出入,说明表还没建好或改动没生效,此时发现比生成完代码再发现便宜得多。

推导规则也在这一步确认。表名 brands → 模块目录 brand → 主类名 Brand(复数转单数、全小写拼接、PascalCase 类名),生成的文件会落在:

server/app/model/brand/Brand.php
server/app/repository/brand/BrandRepository.php
server/app/service/brand/BrandService.php
server/app/adminapi/controller/v1/brand/BrandController.php
server/app/adminapi/validate/v1/brand/BrandValidate.php
server/app/adminapi/route/brand.php
admin/src/api/brand.ts
admin/src/views/.../brand/index.vue、components/BrandForm.vue

3. 生成基础骨架

bash
cd server
php think make:crud brands --module=brand --model=Brand

或在管理后台「开发工具 → 代码生成器」里可视化操作。产物清单、字段类型映射规则见 CRUD 生成规范

这一步产出的是能跑通的完整基础 CRUD:列表分页、搜索、新增、编辑、删除、状态切换,前后端都有。此时刷新后台(配置好菜单后,见第 6 节)就已经能用了。

4. 用 AI 做业务增量

骨架不覆盖的业务逻辑交给 AI。以「批量启用 / 禁用品牌」为例,在对话里说:

text
给 brand 模块增加批量启用和批量禁用功能,接收 ids 数组

装了引导资产的助手会按标准流程自己执行:读现有 BrandController / BrandService / 路由文件学风格 → 查 get_conventionsroute 主题确认批量动作怎么命名 → 写代码 → 预览 → 落盘 → 校验。

它应该产出这样的路由(框架规范:多词动作用连字符,对应方法名用 camelCase):

php
Route::group('brand', function () {
    Route::get('list', 'v1.brand.BrandController/list');
    Route::post('batch-enable', 'v1.brand.BrandController/batchEnable');
    Route::post('batch-disable', 'v1.brand.BrandController/batchDisable');
})->middleware(['admin_auth', 'admin_permission', 'admin_log']);

业务方法追加在 Service 上,查询仍然下沉到 Repository:

php
public function batchUpdateStatus(array $ids, int $status): bool
{
    $result = $this->brandRepository->batchUpdate($ids, ['status' => $status]);
    $this->trigger('brand.status_changed', ['ids' => $ids, 'status' => $status]);
    return $result;
}

增量的边界

在骨架文件上追加方法,不要改动骨架已有方法的签名,也不要把新逻辑写进 Controller。副作用(日志、通知、缓存清理)用 $this->trigger() 交给 Listener,别内联。完整的增量原则见 CRUD 生成规范 第 4、5 章。

5. 预览、落盘、校验

AI 写盘走的是固定三步,你只需要在第二步点确认:

text
apply_patch(dry_run=true)   → 列出将新增/覆盖哪些文件、各多少行
     ↓ 你确认
apply_patch(dry_run=false)  → 真正写入磁盘

run_check                   → php -l 语法检查 + 路由注册验证

run_check 出现 ✗ 时,把报错原文丢回对话即可——错误信息里带着具体行号和路由注册失败堆栈,助手能据此定位修正,然后重新落盘、重新校验,直到全绿。

不要把「已生成」当成「已完成」

run_check 只保证语法正确、路由能注册,不保证业务逻辑对。生成完仍要自己跑一遍接口、看一眼数据。

6. 配置菜单与权限

代码就位后,功能还进不了后台导航——菜单和权限节点是数据,不是代码。写入 server/public/install/data/init.sqlmenus 表:

  • 二级菜单(品牌列表页)挂在对应一级菜单下,按 x00 段惯例分配 ID;
  • 三级记录是按钮权限(新增 / 编辑 / 删除 / 批量操作),permission 字段与 Controller 上的权限标注对应。

插入前务必先查已用 ID

menus.id 是全局主键,一级、二级、按钮 ID 混在一起排号,直接猜必然冲突。查已用 ID 的命令、各模块的号段惯例、实地核实过的一级菜单清单,全部在业务模块规范 第 3 章——照着做,别让 AI 凭印象填 ID。

前端源码改动后需要构建,产物是 git 跟踪的:

bash
cd admin && pnpm run build

7. 完整链路回顾

text
设计表(注释写全)
→ schema.sql 同步
→ make:crud 出骨架
→ AI 增量(读现有实现 + 查规范 → 写 → 预览 → 落盘 → run_check)
→ init.sql 配菜单权限
→ admin 构建
→ 验收

8. AI 写歪了怎么办

按出现频率排列的常见偏差,以及纠正话术:

现象原因纠正
字段名对不上(写了 create_time没读真实表结构,用了通用 ThinkPHP 习惯「先调用 show_table_schema 看真实字段再改」
Controller 里直接写 Db:: 查询跨层了「查 get_conventions 的 architecture 主题,按分层改」
路由动作乱命名(brandList没遵循路由细则「查 get_conventions 的 route 主题,按动作命名规范改」
手写了整套基础 CRUD绕过了生成器「基础 CRUD 用 make:crud 生成,你只做增量」
改完不校验就说完成了流程没走完「跑 run_check,有 ✗ 修到全绿」

这些偏差在装了引导资产(init_client_assets)之后会明显减少——规约常驻在助手上下文里,标准流程也写进了 skills。仍然出现时,多半是资产版本过时,用 get_project_info 看一眼 client_assets 是否显示 outdated

相关文档

基于 MIT 许可发布