Skip to content

10.6 自定义模板开发 ​

概述

代码生成器使用 PHP 原生模板引擎渲染代码,模板文件存放在 templates/ 目录下。修改模板即可自定义生成代码的格式。

模板目录结构 ​

text
templates/
├── controller.php.tpl          # 控制器模板
├── logic.php.tpl               # 业务逻辑模板(含 serializeMaps、导入导出)
├── model.php.tpl               # 模型模板
├── validate.php.tpl            # 验证器模板
├── ui/                         # 普通列表模板(6个前端文件)
│   ├── api.ts.tpl              # API 接口模块模板
│   ├── index.vue.tpl           # 列表页模板
│   ├── edit.vue.tpl            # 编辑弹窗模板
│   ├── detail.vue.tpl          # 详情弹窗模板
│   ├── columns.ts.tpl          # 表格列配置模板
│   └── querySchemas.ts.tpl     # 查询表单配置模板
└── ui2/                        # 树形结构模板(4个前端文件)
    ├── api.ts.tpl
    ├── index.vue.tpl
    ├── edit.vue.tpl
    └── detail.vue.tpl

模板变量 ​

模板使用 PHP 原生语法,变量通过 GeneratorService::buildTemplateVars() 构建,渲染时通过 extract($vars) 注入。

基础信息变量 ​

变量类型说明示例
$app_namestring应用名(路由前缀)tool
$module_namestring模块名(小写下划线)example
$module_commentstring功能名称(表注释清洗后)案例
$model_class_namestring模型类名(大驼峰)Example
$model_class_name_camelstring模型类名(小驼峰)example
$route_prefixstring路由前缀example
$api_pathstringAPI 路径tool/example
$permission_prefixstring权限码前缀sys:example
$primary_keystring主键字段名id
$table_namestring表名(不含前缀)example

树形结构变量 ​

变量类型说明示例
$is_treebool是否为树形结构true
$parent_id_fieldstring父级字段名parent_id
$parent_id_field_camelstring父级字段名(驼峰)parentId
$display_fieldstring显示字段名name
$display_field_camelstring显示字段名(驼峰)name

字段列表变量 ​

变量类型说明
$fieldsarray全部字段列表
$list_fieldsarray列表页展示字段(排除隐藏字段)
$form_fieldsarray表单字段(编辑弹窗用)
$filter_fieldsarray筛选字段(搜索表单用)
$file_fieldsarray文件/图片字段名列表
$content_fieldsarray富文本字段名列表
$like_fieldsarray模糊搜索字段名列表
$eq_fieldsarray精确匹配字段名列表
$unique_fieldsarray唯一性校验字段名列表
$validate_rulesarray验证规则
$validate_messagesarray验证提示信息
$validate_fieldsarray需验证的字段列表
$serialize_mapsarray枚举字段 → 字典编码映射
$foreign_keysarray外键关联信息

功能标记变量 ​

变量类型说明
$has_importbool是否生成导入方法
$has_exportbool是否生成导出方法
$has_image_fieldbool是否包含图片字段
$has_rich_text_fieldbool是否包含富文本字段
$has_sortbool是否包含排序字段
$is_tree_structurebool是否为树形结构($is_tree 别名)
$template_typestring模板类型:ui 或 ui2

排序变量 ​

变量类型说明示例
$order_fieldstring默认排序字段id 或 sort
$order_typestring默认排序方向desc 或 asc

字段结构 ​

每个字段为一个数组,包含以下属性:

php
$field = [
    'name'       => 'status',        // 字段名(下划线)
    'camel_name' => 'status',        // 字段名(驼峰)
    'label'      => '状态',           // 中文标签(取字段 COMMENT)
    'type'       => 'IntegerField',   // 字段类型归一化后的类名
    'db_type'    => 'int',            // 原始数据库类型
    'default'    => 0,                // 默认值
    'is_image'   => false,            // 是否为图片字段
    'is_rich_text' => false,          // 是否为富文本字段
    'choices'    => [                 // 选项列表(有值时可生成 ElTag 渲染)
        ['value' => 0, 'label' => '正常', 'type' => 'success'],
        ['value' => 1, 'label' => '禁用', 'type' => 'danger'],
    ],
];

模板语法 ​

模板使用 PHP 原生语法,通过 <?php echo ?> 输出变量,使用 <?php foreach ?> 等控制结构:

后端模板示例(logic.php.tpl 片段) ​

php
<?php echo '<?php' ?>

declare(strict_types=1);

namespace app\logic;

use app\BaseLogic;
use app\model\<?php echo $model_class_name ?>;

class <?php echo $model_class_name ?>Logic extends BaseLogic
{
    protected string $modelClass = <?php echo $model_class_name ?>::class;
    protected string $validateClass = \app\validate\<?php echo $model_class_name ?>Validate::class;

<?php if (!empty($file_fields)): ?>
    protected array $fileFields = [<?php echo implode(', ', array_map(fn($f) => "'$f'", $file_fields)) ?>];
    protected string $fileSaveDir = '<?php echo $module_name ?>';
<?php endif; ?>

<?php if (!empty($serialize_maps)): ?>
    protected array $serializeMaps = [
<?php foreach ($serialize_maps as $field => $dict): ?>
        '<?php echo $field ?>' => '<?php echo $dict ?>',
<?php endforeach; ?>
    ];
<?php endif; ?>
<?php if ($is_tree): ?>

    protected string $treeParentField = '<?php echo $parent_id_field ?>';
    protected string $treeLikeField = '<?php echo $display_field ?>';
<?php endif; ?>
}

前端模板示例(columns.ts.tpl 片段) ​

typescript
import { h } from 'vue';
import { ElAvatar, ElTag } from 'element-plus';

export const columns = [
  { type: 'selection' },
  { label: 'ID', prop: 'id', fixed: 'left', width: 50 },
<?php foreach ($list_fields as $field): ?>
  {
    label: '<?php echo $field['label'] ?>',
    prop: '<?php echo $field['camel_name'] ?>',
<?php if ($field['is_image']): ?>
    render(record) {
      return h(ElAvatar, { size: 48, src: record.row.<?php echo $field['camel_name'] ?> });
    },
<?php elseif ($field['choices']): ?>
    render(record) {
      const map = {
<?php foreach ($field['choices'] as $choice): ?>
        <?php echo $choice['value'] ?>: { text: '<?php echo $choice['label'] ?>', type: '<?php echo $choice['type'] ?>' },
<?php endforeach; ?>
      };
      const s = map[record.row.<?php echo $field['camel_name'] ?>];
      return h(ElTag, { type: s?.type || 'info' }, { default: () => s?.text });
    },
<?php endif; ?>
  },
<?php endforeach; ?>
];

自定义模板步骤 ​

  1. 修改 templates/ 目录下的 .tpl 文件
  2. 使用上述模板变量($model_class_name、$module_comment 等)
  3. 下次生成时自动使用新模板

注意事项

  • 修改模板后,已生成的代码不会自动更新
  • 模板中不能使用短标签 <?= ?>,必须用 <?php echo ?>(渲染前有预检)
  • 模板文件不能含 UTF-8 BOM 头
  • 树形结构模块使用 ui2/ 模板,普通模块使用 ui/ 模板

模板选择逻辑 ​

text
表结构中包含 parent_id 或 pid 字段?
    │
    ├─ 是 → 使用 ui2/ 树形模板(自动,无需手动选择)
    │
    └─ 否 → 使用 ui/ 普通列表模板

生成的前端文件 ​

ui/ 模板生成 6 个文件(ui2/ 生成 4 个,无 columns.ts 和 querySchemas.ts):

文件说明引用关系
api.tsAPI 接口模块被 index.vue、edit.vue 导入
index.vue列表页导入 columns.ts、querySchemas.ts
edit.vue编辑弹窗被 index.vue 动态加载
detail.vue详情弹窗被 index.vue 动态加载
columns.ts表格列配置被 index.vue 导入,含 ElTag/ElAvatar 渲染
querySchemas.ts查询表单配置被 index.vue 导入,含 Select/Input/DatePicker 组件

相关文档 ​

小蚂蚁云团队 · 提供技术支持