7.0 KiB
10.4 表结构解析引擎
:::tip 概述 解析引擎读取数据库表的字段信息(名称、类型、注释、是否必填等),并自动分析字段属性(图片、富文本、选项等),作为代码生成的数据源。支持 MySQL、PostgreSQL、SQL Server、Oracle、SQLite 五种数据库。 :::
多数据库适配
// app/Services/GeneratorService.php
// 根据默认数据库驱动分发到对应的查询实现
public function getTableList(): array
{
$driver = config('database.default');
return match ($driver) {
'sqlite' => $this->queryTableListSqlite(), // sqlite_master
'mysql' => $this->queryTableListMysql(), // SHOW TABLE STATUS
'pgsql' => $this->queryTableListPgsql(), // information_schema.tables
'sqlsrv' => $this->queryTableListSqlsrv(), // sys.tables
'oracle' => $this->queryTableListOracle(), // all_tables
default => $this->queryTableListMysql(),
};
}
每种驱动还实现了对应的列解析方法(PRAGMA table_info / information_schema.COLUMNS / pg_attribute 等),输出统一的字段结构。
基础解析内容
| 信息 | 用途 |
|---|---|
| 字段名 | 生成属性名、查询条件 |
| 字段类型 | 生成验证规则、表单组件 |
| 字段注释 | 生成标签名、注释 |
| 是否必填 | 生成 required 验证规则(!isNull && default === null) |
| 默认值 | 生成默认值配置 |
| 字段顺序 | 表单 / 列表字段顺序与表结构保持一致 |
字段类型映射
原始类型先经 parseFieldType() 归一化(boolean / int / decimal / varchar / text / datetime / date / time,无法识别归为 varchar),再由 toConfigType() 映射为配置类名:
| 数据库类型 | 归一化类型 | 配置类名 | 表单组件 | 验证规则 |
|---|---|---|---|---|
| VARCHAR | varchar | CharField | Input | max:N |
| TEXT | text | TextField | Editor | - |
| INT / BIGINT / SMALLINT | int | IntegerField | InputNumber | number |
| TINYINT | int(tinyint(1)/bit → boolean) |
IntegerField / BooleanField | Select / Radio / Switch | in:0,1 |
| DECIMAL / FLOAT / DOUBLE | decimal | DecimalField | InputNumber | float |
| DATETIME / TIMESTAMP | datetime | DateTimeField | DatePicker | date |
| DATE | date | DateField | DatePicker | date |
| TIME | time | TimeField | TimePicker | - |
| BOOLEAN / BIT | boolean | BooleanField | Switch | - |
字段自动识别规则
解析引擎会自动分析每个字段的属性,识别规则如下:
图片字段
| 条件 | 规则 |
|---|---|
| 类型 | VARCHAR |
| 匹配 | 注释或字段名匹配 /图片|封面|头像|logo|icon|image|avatar|photo/i |
识别后:is_image = true,归入 file 字段组,前端用 NAvatar 渲染。
富文本字段
| 条件 | 规则 |
|---|---|
| 类型 | TEXT |
| 匹配 | 注释匹配 /内容|详情|正文/i |
识别后:is_rich_text = true,归入 content 字段组,自动处理临时文件和图片占位符。
多行文本字段
| 条件 | 规则 |
|---|---|
| 类型 | VARCHAR |
| 匹配 | 注释匹配 /备注|说明|描述|介绍|简介/i |
识别后:is_textarea = true,前端用 textarea 组件渲染。
选项字段(枚举)
解析引擎从字段注释中自动解析选项(parseChoicesFromComment()),支持以下注释格式:
状态:1-启用 2-停用 ← 中文冒号 + 数字-文字
状态:1-启用 2-停用 ← 英文冒号 + 数字-文字
类型:1:制造业 2:旅游业 ← 中文冒号 + 数字:文字
执行策略:1-立即执行 2-执行一次 3-放弃执行
解析规则:
- 以冒号(中文
:或英文:)分割,取冒号后面的部分 - 匹配
数字-文字或数字:文字格式(正则(\d+)\s*[\-\:]\s*(.+?)(?=\s+\d+[\-\:]|$)) - 每个匹配项生成一个选项:
{value: 数字, label: 文字, type: 标签颜色}
标签颜色映射(guessChoiceTagType()):
| 选项值 | 标签颜色 | 标签 type |
|---|---|---|
| 1 | 绿色 | success |
| 2 | 红色 | danger |
| 3 | 橙色 | warning |
| 其他 | 灰色 | info |
识别后:choices 数组非空,自动归入 eq 字段组(精确匹配)和 serialize_maps(字典映射,编码为 {模块名}_{字段名})。
状态字段自动补全
| 条件 | 规则 |
|---|---|
| 字段名 | status |
| 类型 | int |
| 前提 | 注释中未解析出选项 |
自动生成默认选项:
| 值 | 标签 | 颜色 |
|---|---|---|
| 0 | 正常 | success |
| 1 | 停用 | danger |
模糊搜索字段
| 条件 | 规则 |
|---|---|
| 类型 | VARCHAR |
| 匹配 | 字段名匹配 /名称|标题|name|title|username|realname/i |
识别后:归入 like 字段组,分页查询时 LIKE 匹配,同时加入筛选表单。
唯一字段
| 条件 | 规则 |
|---|---|
| 匹配 | 字段名匹配 /编码|code|username|mobile|email|account/i |
识别后:归入 unique 字段组,新增/修改时由 Service 层自动校验唯一性(见 10.5 与 3.5 Service 层开发)。
排序字段
| 条件 | 规则 |
|---|---|
| 字段名 | sort |
识别后:has_sort = true,默认排序改为 sort asc(order_field / order_type 变量,而非 id desc)。
系统字段排除
以下字段自动从表单和列表中排除:
id、tenant_id、create_user、create_time、update_user、update_time、is_delete
字段注释清洗
注释中的选项部分会被自动移除(cleanFieldComment()),只保留中文名称:
"案例状态:1-正常 2-禁用" → "案例状态"
"执行策略:1-立即执行 2-执行一次 3-放弃执行" → "执行策略"
安全校验
// 表名合法性校验(防 SQL 注入)
protected function validateTableName(string $tableName): string
{
if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $tableName)) {
throw new \Exception('表名格式不合法: ' . $tableName);
}
return $tableName;
}
:::warning 安全提示
涉及表名拼接的 SQL 一律先经 validateTableName 校验,只允许字母、数字、下划线,防止 SQL 注入。所有表名解析入口(parseTableStructure 及各驱动的列查询)都会先调用该方法。
:::
自动创建的权限节点
生成菜单时(createMenu()),自动创建以下 9 个权限节点:
| 权限码 | 说明 |
|---|---|
sys:{模块名}:page |
分页查询 |
sys:{模块名}:list |
列表查询 |
sys:{模块名}:detail |
详情查询 |
sys:{模块名}:add |
新增 |
sys:{模块名}:update |
编辑 |
sys:{模块名}:delete |
删除 |
sys:{模块名}:batchDelete |
批量删除 |
sys:{模块名}:import |
导入 |
sys:{模块名}:export |
导出 |