随着现在框架发展的发展,本来已经放弃了这个项目。但现在依然看到大量的底层码农在写增删改查,实在受不了。于是连夜捡起这个项目。
能直接无代码实现增删改,直接解放后端苦逼码农。
### CGF(Comment Generate Form)
根据表字段注释自动实现CURD。只要建好表就拥有了添加,修改,列表,搜索基本功能的接口。
### 安装 install
composer require rrbrr/cgf
### thinkphp中使用方法(支持thinkphp8)
####1. 直接去vendor/rrbrr/cgf/Error.php复制到app/controller中
####2. 手工在app/controller目录下创建Error.php文件,写入以下代码
```php
<?php
namespace app\controller;
use Cgf\Framework\Thinkphp\BaseController;
class Error extends BaseController
{
public function __call($method, $args)
{
return 'error request!';
}
}
```
#### 3. 然后就直接访问 /表名/index,如 /article/index,/article/save
###默认支持以下方法,如果想修改可以打开Cgf\Framework\Thinkphp\BaseController自己修改
1. index 列表
2. save 添加/保存
3. delete 删除
比如建个文章表
```sql
CREATE TABLE `article` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) DEFAULT NULL,
`content` text,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4;
```
然后就可以用curd api接口了。
1. 添加新文章
http://www.test.com/article/save?title=标题&content=内容
```json
{
"code": 1,
"msg": "成功",
"data": {
"id": "1"
}
}
```
2. 文章列表
http://www.test.com/article/index
```json
{
"code": 1,
"msg": "成功",
"data": {
"total": 1,
"per_page": 20,
"current_page": 1,
"last_page": 1,
"data": [{
"id": 1,
"title": "标题",
"content": "内容",
"create_time": "2020-07-17 18:58:44"
}]
}
}
```
搜索可以直接指定字段及关键字即可,如:http://www.tesuo.com/article/index?title=标题
3. 文章详情
http://www.test.com/article/show?id=1
```json
{
"code": 1,
"msg": "成功",
"data": {
"vo": {
"id": 1,
"title": "标题",
"content": "内容",
"create_time": "2020-07-17 18:58:44"
}
}
}
```
4. 修改文章
http://www.test.com/article/save?id=1&title=新标题
```json
{
"code": 1,
"msg": "成功",
"data": {
"id": ""
}
}
```
# 设计思想
根据每个功能的配置文件来生成对应的表单界面,验证规则,sql查询字段。
流程
1.定义配置
```
return array(
'base' =>
array(
'username' =>
array(
'name' => 'uesrname',
'type' => 'text',
'size' => 10,
'zh' => 'id',
),
'status_flag' =>
array(
'name' => 'status_flag', //数据表字段名
'type' => 'text', //类型
'size' => 10,
'rawOption' => '0:禁用,1:正常', //可选值
'options' =>
array(
0 => '禁用',
1 => '正常',
),
'zh' => '用户状态', //后台列表中展示的标题
'show_text' => 'status_flag_text', //将枚举的数学类型的值转为文本显示
),
)
);
```
2.解析配置,生成相应的模板文件和后端处理程序。
##### 一般情况不会手工写这个配置,都是根据表的定义来自动生成。 表格式如下说明(详细文档见doc目录中):
# 表定义的参考格式
```sql
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '标题-hidden|0111',
`username` varchar(255) NOT NULL DEFAULT '' COMMENT '用户名--用户名为字符|1111-0011-11|require:用户名必须填写-unique-<</\\w{3,6}/i>>:用户名不合法',
`password` varchar(255) DEFAULT '' COMMENT '密码-password|1100-1110-0|require:密码必须填写',
`email` varchar(255) DEFAULT NULL COMMENT '邮箱|15-12-3|require:邮箱必须填写-email:邮箱格式不正确',
`birthday` date DEFAULT NULL COMMENT '生日|1111|require:密码必须填写',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态-select-禁用则不显示|1111|require|0:禁用,1:正常,2:审核中',
`create_time` datetime DEFAULT NULL COMMENT '创建时间|0010',
`flag` varchar(255) NOT NULL DEFAULT '' COMMENT '标记-select|1100|require|function=flag_options()|tpl_function=img()',
`intro` text COMMENT '用户介绍-editor|1100-1100-11',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表|lock-birthday|编辑:id,查看用户浏览记录:id| add-export-showMenu';
```
# 参考格式说明
### 用户名--用户名为字符|1111|require:用户名必须填写-unique-<</\w{3,6}/i>>:用户名不合法
#### [ 用户名 ] 控件label
#### [ - ] 光有1个[ - ],没有内容,表示省略了内容,也就是省略了个控件类型,使用默认的控件类型
### [ 用户名为字符 ],表示tip提示信息
#### [ 1111 ] 表示用户名在增加,修改,列表,搜索页面都显示
#### [ require ] 表示必填, unique表示为惟一,
#### [ <</\w{3,6}/i>>:用户名不合法 ] 正则验证用户名,此正则意思是,用户名为3到6位的字符,并且不符合此正则的则报错 “用户名不合法”
### 状态-select-禁用则不能访问 | 15| reqiure:必须填写 | 0:禁用,1:正常,2:审核中
#### [ 状态 ] 控件label名为
#### [ select ] 表示使用select控件
#### [ 禁用则不能访问 ] 表示提示内容为
#### [ 15 ] 为1111的10进制,等同于1111
#### [ reqiure:必须填写 ] 表示必填,错误提示为:必须填写
#### [ 0:禁用,1:正常,2:审核中 ] 表示状态这个select控件有3个选项,0,1,2表示key
# 字段注释格式说明
以 |-,之类的做分隔
注释标题 - htm控件类型 - 提示 |后台显示页面-用户中心-前台显示页面 | 验证类型1-验证类型2 | 选项|显示模板
## 第一部分 描述字段lable、控件类型、提示信息
注释标题: 一般是字段的中文标题,form表单的label
html控件类型: select,checkbox,input,textare,datepicker,editor等,更多的控件需要你自己来实现。
提示:一般是此字段的填写规范,如:允许字母或数字
## 第二部分 描述在哪些页面显示
1. 位表示法(1表示显示,0不显示)
添加页|修改页|列表页|搜索页
---|---|---|---
1 | 1 | 0 | 0
以上表示在添加和修改页显示此字段
2. 10进制表示法,就是上面的位表示法将二进制数转成10进制数
添加页|修改页|列表页|搜索页
---|---|---|---
1 | 1 | 0 | 0
1100 转成 10进制 = 12
也就是说,12也表示添加页,修改页显示字段。
更多例子:
添加,修改,列表,搜索全显示 1111 = 15
添加,修改,列表都要显示则是 1110 = 14
添加,修改显示,列表不显示 1100 = 10
添加,修改不显示,列表显示,一般像创建时间就是这样 0010 = 1
如果一个项目有多个模块,每个模块显示不同的字段。则可以根据模块来配置。多个模块之间用 - 分隔。目前内置3个模块
后台 - 用户中心 - 前台
如 1111-0011-11 表示后台所有页面显示,用户中心在列表和搜索页显示,前台在列表和详情页显示。
由于前台一般只有列表和搜索页,所以只有2位。
## 第三部分 描述前后台校验方式
校验类型:reqiure,email,username,mobile等,用于后台校验,对应thinkphp的校验格式 ,
也支持前台验证,目前使用validform验证格式,也可使用正则表达式。
## 第四部分 描述选项的key和value
选项: 选项1:选项1值,选项2:缺项2值
## 第五部分 回调函数处理
比如保存多选的tag时,页面上传过来的是个数组 tag = [a,b,c] ,但想保存为 a,b,c,则此字段可使用函数回调来处理
写法 implode=\,,###
等号前面是函数名,后面是参数,用逗号分隔。像implode函数,第一参数就是逗号,则需要转义写为 \\,
# 表本身注释格式说明
表的中文名|属性|操作|排序|页面按钮
1. 表的中文名:表示表的作用。
2. 属性: 可选值有 lock,lock表示生成相关cgf文件后,会锁定配置文件,再次修改不会生成新配置文件。
3. 每行记录的操作:
记录可以进行的操作项
常用有:编辑,删除。
写法:edit:编辑:id, edit表示js的方法名,编辑表示页面上显示的中文名,id表示参数
4. 排序
默认排序字段-倒序
5. 页面按钮 页面上显示的按钮,用 - 分隔
可选值:add,export,showMenu
add 显示添加按钮
export 显示导出按钮
showMenu 在左侧菜单显示
例:用户表|lock|edit:编辑:id,del:删除:id|create_time-desc|export-showMenu|function_name
# 函数使用
1.show_func 显示列表数据时,调用函数,参数为当前字段的值。
2.tpl_function=img() 会被解析成配置 ['flag'=>['tpl_function'=>'img()']
3.选项字段也可定义函数,function=flag_options()将会调用flag_options返回所有选项
例1:显示支付方式。
```
//cgf 格式
`channel` varchar(255) DEFAULT '' COMMENT '支付渠道|0011-0-11|require|show_func=get_pay',
// channel值一般是 alipay,wxpay等。但希望显示出来的是支付宝,微信。就可以用函数来处理了。
//php 代码
function get_pay($selfValue){
$paymethod = ['alipay'=>'支付宝','wxpay'=>'微信'];
return $paymethod[selfValue];
}
//这样在列表里就能看到支付方式的汉字了,而不是字母代号
```
例2:多参数支持,显示产品详情链接.订单里显示产品名,想要点击能打开产品详情,详情页需要传产品id参数,可用下面方式。
方式一:
```
//cgf格式
`course_title` varchar(255) NOT NULL DEFAULT '' COMMENT '产品名称|1011||show_func=order_course_title',
//php
function order_course_title($title,$key,$v){ // 调用代码:call_user_func_array(函数名,[字段值,字段名,此行记录所有数据]);
$title = $v['course_title'];
$url = "http://www.21mmm.com/course/{$v['course_id']}";
$url = "<a href='{$url}' target='_blank' title='{$title}'>$title</a>";
return $url;
}
```
方式二:在函数名后,指定参数course_id。 未来也可以实现可编程方式。
如: |fcuntion order_course_title(course_id), 直接写代码,然后通过程序来解释cgf代码
```
//cgf格式
`course_title` varchar(255) NOT NULL DEFAULT '' COMMENT '产品名称|1011||show_func=order_course_title-course_id',
//php
function order_course_title($title,$key,$course_id){
$title = $v['course_title'];
$url = "http://www.21mmm.com/course/{$v['course_id']}";
$url = "<a href='{$url}' target='_blank' title='{$title}'>$title</a>";
return $url;
}
```
未来支持默认函数调用,如order表user_id字段 "用户id|1111||show_func" 不用加=指定函数,只要定义了show_func,就会默认调用 order_user_id()这个函数
例2:显示分类名。 分类一般用分类id关联,但显示时,却希望显出中文。
```
// cgf格式
`category_id` int(11) unsigned NOT NULL COMMENT '分类id-select|1111|require|function=get_select_by_category',
//php 代码
function get_select_by_category(){
$r = M('Category')->field('id,title')->select();
return $r; //从分类表,取出分类id,分类title
}
//这样category_id 显示的select就会是这样的 <option value="分类id1">分类tilte1</option>
```
# 配置
``` php
$cgfConf = []; //
$cgfConf['dbConfig'] = ['host'=>'localhost','dbname'=>'test','username'=>'root','password'=>'123456','type'=>'mysql']; //数据库连接配置
$cgfConf['savePath'] = $appBasePath . "/Cgf/definition"; //保存cgf生成的定义文件
$cgfConf['framework'] = 'thinkphp'; //使用的框架
$cgfConf['validate'] = 'thinkphp'; //使用验证
$cgfConf['form'] = 'bootstrap'; //表单使用的框架
$cgfConf['currentName'] = 'common'; //当前模块名
$cgfConf['tableName'] = $tableName; //表名
$cgfConf['controllerName'] = $this->controllerName; //控制器名
$cgfConf['appRootPath'] = $appBasePath; //框架应用程序根目录
$cgfConf['parentTemplatePath'] = $appBasePath . '/view/public/'; //cgf生成模板使用的父模板,cgf会根据这里的模板来生成应用模板
$cgfConf['templateSavePath'] = $appBasePath . "/view/{$tableName}"; //cgf生成的模板保存路径
$cgfConf['availableModule'] = ['common', 'admin']; //可用模块
$cgfConf['autoHiddenPrimaryKey'] = true; //是否将主键表单类型设为hidden
```
# 跨库支持
```
$dbConnection= [
'DB_TYPE'=>'mysql',
'DB_HOST'=>'localhost',
'DB_PORT' => '3306',
'DB_NAME'=>'test',
'DB_USER'=>'root',
'DB_PWD'=>'123456',
'DB_PREFIX'=>'',
]
//在实例化的时候传入db连接即可
$tableInfo = new TableInfo('edit',$dbConnection);
```
#目录结构和设计说明
definition 是所有表定义
Form下是具体表单的实现类,继承Form.class.php
Validate下是各框架下的验证实现,继承Validate.php
#definition结构说明
#### [模块名][页名]
### 模块名有下列项目
admin 后台
user 用户中心
home 前台
### 页面有下列项目
all 所有字段定义,等于list定义
add 添加页
edit
list
search
# 数组定义使用方法
## 公共属性
##### name 表单名,一般和字段名相同
##### type 表单类型,所有表单类型的实现都在Form目录下,要继承Form类
1. 所有html表单类型都可以。如text,select
2. 自定义类型
editor 富文件编辑器
img 图片上传,带图片预览
file 文件上传
files 多文件上传
datepicker(日期选择控件)
datetimePicker(时间选择控件)
datePickerRang(日期范围选择控件)
datetimePickerRang(时间范围选择控件)
##### size 表单的尺寸,一般用于text文本框
##### zh 中文标签名
##### options 当表单类型是select时的选项,checkbox,radio也可以有此字段。
1.枚举格式。 如
```php
'options'=>[
0=>'禁用'
1=>'正常',
2=>'审核中'
]
```
2.函数获取。 如
```php
'options'=>[
'function'=>"get_allf_lag('a','###','@@@')"
]
```
##### rawOption 数据表字段的原生定义,一般只有表字段定义了选项,才会有。
如 'rawOption' => '0:否,1:是'
##### validate 验证规则
验证规则可以有多个,会依次执行验证。
```php
'validate' => [
['require:必须填写',]
['<</\w{3,6}/i>> : 用户名不合法'],
['checkUsername:用户名已经被使用了'],
]
```
##### autoComplete
#### 实例
zh 对应字段含义
base=>[
'flag'=>[
'name'=>'标致',
'type'=>'select',
'options'=>[
'function'=>"get_allf_lag('a','###','@@@')"
]
]
'create_time'=>[
'name'=>'创建时间',
'type'=>'datetime',
],
]
//添加页用时间选择组件
add=>[
'create_time'=>[
'name'=>'创建时间',
'type'=>'datetimePicker',
]
]
//搜索页用时间范围组件
search=>[
'create_time'=>[
'name'=>'创建时间',
'type'=>'datetimePickerRang',
]
]
//标题文本框
base=>[
'title'=>[
'name'=>'标题',
'type'=>'input', //常规是文本框
]
]
search=>[
'title'=>[
'name'=>'标题',
'type'=>'linkbutton', //列表页是链接,点击进入编辑页或跳转到其它页面。只有后台这样。
]
]
对于create_time添加页和搜索页使用不同组件问题,sql不太好定义。最好用config.非要用sql,也用创建时间-datepicker|datetimePicker
但这种方式也不能解决各模块组件不同的问题。如用户中心搜索页,添加页和后台搜索页,添加页都用不同组件的问题。
## base
base 通常是表的所有字段字义,其它表的定义如果要显示关联表的某些字段值,那些显示的字段的信息就是从base里取出来的。
例如:
搜索框增加选项步骤
1.可在base里添加相应的字段。
2.在search里增加。
## 组件
1.搜索页,根据配置生成输入框,日期选择控件等。但select的选项值却是在生成组件后,再调用函数生成的。
可以将select选项直接与输入框这些控件生成是一起生成。若是回调函数则也是生成组件时调用回调函数。这样避免生成select时来回交互。简化流程。这样就需要在form里实现自己完整的组件,不能依赖于tp的组件了。
## 列表
1.关联表
related_table 关联表定义,相当于join
related_field 关联表中对应的字段,相当于join时右表的关联字段
table_name 关联表
fields => ["state","name"], 关联表要显示的字段
"way" => "add", 展现方式,
add表示左表的字段也显示,右表字段也显示。
replace表示左表字段不显示,用右表的字段代替
例:
"related_table" => [
"related_field" => "issue_id",
"table_name" => "goods_activity",
"fields" => ["state"],
"way" => "add",//replace 1.add表示显示user_id,并且增加field定义的字段 2.replace 表示用field字段替换掉user_id
'function'=>"date"
]
2.show_text 数字枚举字段,显示对应的文字含义
3. "class"=>"c_trans_state",//给列表表格单元格增加样式,便于js能定位到相应的单元格
函数定义
### 代表字段本身的值,
@@@代表本行记录的值,有时需要引用其它字段的值参数计算,就用@@@传递行记录的所有值
col
1.'function'=>'date("y-m-d","###")'; //将被解析为 date("y-m-d",$v['col']);
2.'function'=>'getData('a','###','@@@')';//将被解析为 getData("a",$v['col'],$v);
## 搜索
## 编辑
## 添加
SqlToCgfDefinition.php
根据表定义生成cgf配置文件
sql表定义解析后的数组
```
"title"=>[
"name"=>"title",
"zh"=>"标题",
"arrShowPage"=>
["admin"]=>
"add",
"edit",
"list",
"search"
["user"]=>
"add",
"edit",
"list",
"search"
["home"]=>
"list",
"show"
]
```
1.单模块
$cgf=["base"=>['字段1'],"list"=>['字段1']]
2.多模块
$cgf['admin']=["base"=>['字段1','字段2','字段3'],"list"=>['字段1']]
$cgf['user']=["base"=>['字段1','字段2','字段3'],"list"=>['字段2']]
$cgf['home']=["base"=>['字段1','字段2','字段3'],"list"=>['字段3']]
# 不支持的功能
1.三表关联。如:订单表通过user_id关联用户表,用户表通过手机号关联所在地区表。这时想在订单列表显示用户手机号可以,但无法再关联到地区表,显示用户所在城市。
====================================================================
# 截图


# 下一步支持
1.字段的fuction可以区分是后端function,还是前端function.
如排序字段,后台列表希望显示出的是个可编辑的input,这样直接就能在列表页更改排序。
如果不区分的话,后台function将字段变成<input type="text"> ,前台列表接口sort字段获取到也是这个html,那就完完了。
所以可以用php_function表示是个后端函数,tpl_function表示模板函数,js_fuction表示js函数
如:后台商品表有display字段表示显示状态,数据库值为0,1.但在后台和用户中心希望通过函数转为文字,但返回到前台的接口,希望显示原始值,这样前端页面可以根据1或0来判断,是上架按钮,还是下架按钮。
但这种情况下,后台也需要有对应的功能。
商品名 显示状态 操作
苹果6手机 上架中(通过函数将display的值1转为文本“上架中”) 下架(通过if(dispaly==1)则显示此文字)
此时有两种办法
1.if(display=='上架') 显示下架
2.增加个display_text字段,列表展现时,显示display_text的内容
感觉都不科学
可以试播-select|1111||0:否,1:是
用命名空间和作用域解决
list.function=show 列表调用函数
search.function=show 搜索调用函数
all.function=show //默认所有,可省略
admin.list.function=show 后台列表显示调用函数
显示关联表相应字段
user_id|1111||list.table=field(username,sex)-replace //replace替换,add默认add
# 数组定义使用方法
## 公共
zh 对应字段含义
## 列表
1.关联表
related_table 关联表定义,相当于join
related_field 关联表中对应的字段,相当于join时右表的关联字段
table_name 关联表
fields => ["state","name"], 关联表要显示的字段
"way" => "add", 展现方式,
add表示左表的字段也显示,右表字段也显示。
replace表示左表字段不显示,用右表的字段代替
例:
"related_table" => [
"related_field" => "issue_id",
"table_name" => "goods_activity",
"fields" => ["state"],
"way" => "add",//replace 1.add表示显示user_id,并且增加field定义的字段 2.replace 表示用field字段替换掉user_id
'function'=>"date"
]
2.show_text 数字枚举字段,显示对应的文字含义
3. "class"=>"c_trans_state",//给列表表格单元格增加样式,便于js能定位到相应的单元格
函数定义
### 代表字段本身的值,
@@@代表本行记录的值,有时需要引用其它字段的值参数计算,就用@@@传递行记录的所有值
col
1.'function'=>'date("y-m-d","###")'; //将被解析为 date("y-m-d",$v['col']);
2.'function'=>'getData('a','###','@@@')';//将被解析为 getData("a",$v['col'],$v);
## 搜索
## 编辑
## 添加
SqlToCgfDefinition.php
根据表定义生成cgf配置文件
sql表定义解析后的数组
```
"title"=>[
"name"=>"title",
"zh"=>"标题",
"arrShowPage"=>
["admin"]=>
"add",
"edit",
"list",
"search"
["user"]=>
"add",
"edit",
"list",
"search"
["home"]=>
"list",
"show"
]
```
1.单模块
$cgf=["base"=>['字段1'],"list"=>['字段1']]
2.多模块
$cgf['admin']=["base"=>['字段1','字段2','字段3'],"list"=>['字段1']]
$cgf['user']=["base"=>['字段1','字段2','字段3'],"list"=>['字段2']]
$cgf['home']=["base"=>['字段1','字段2','字段3'],"list"=>['字段3']]
推荐扩展
-
topthink/think-ai
8个月前
-
topthink/think-api
11个月前
-
topthink/think-dumper
Dumper extend for thinkphp
4个月前 -
topthink/think-validate
think validate
5个月前 -
yzh52521/think-mailer
A powerful and beautiful php mailer for All of ThinkPHP and Other PHP Frameworks based Symfony mailer
1年前