您好,欢迎访问一九零五行业门户网

CRUD生成器DBuilder设计与实现

源码位于github:https://github.com/lvyahui8/dbuilder.git 。文中图片如果太小看不清楚,请右键点击“在新标签页中打开”即可看到原图
第一章           引言1.1 研究背景及意义计算机软件技术发展至今,数据库已成为最广泛使用的存储格式化数据的媒介,数据库程序开发技术也日趋完善,大型的orm框架使得数据库程序开发变得简单,并已成为操作关系型数据库的主流方式。数据库程序主要代码为crud(create, retrieve, update, delete)代码,随着orm框架功能的完善,编写crud代码也衍生其固定的流程,对不同数据库表进行操作的crud代码也存在高度可重用性。当前编写重复性的crud代码成为开发人员的常态,不仅严重降低其积极性,而且损失其开发效率,所以迫切需要一种能够快速生成crud代码的产品,以期减少这方面的工作,提高开发效率。
1.2 研究现状目前国外已经诞生一些解决上述需求的、具有很高可用性的crud生成器产品:crudkit,crud-admin-generator,dadabik,grocerycrud,sximobuilder。这些产品各有其特点,但也有一共同点:都是基于php进行开发(这在一定程度上决定于php语法的灵活性及其解析性)。sximobuilder是其中的典型代表,尽管sximobuilder设计独特、可用性高、流行度高,但也存在如下不足之处:
不支持自定义表单控件;不支持多数据库;验证规则不完善,不支持异步验证;代码冗余度极大。然而对于当今日益复杂的web程序,上述几点是开发过程必须考虑的问题,因此,开发一款既具有sximobuilder现有功能、又完善其不足之处的crud生成器产品,势在必行。
1.3 研究内容基于国内外crud生成器研究现状,笔者开发一款名为dbuilder(d为dataadministrator的简写)的crud 生成器。
dbuilder借鉴sximobuilder的模块为代码单元、由模板生成代码的思想,但拥有与sximobuilder完全不同的代码生成器逻辑。它在实现sximobuilder核心的代码生成、通用crud两种功能的基础上,通过重写代码逻辑完善其不足之处:代码冗余度大、缺少前端验证。
第二章           dbuilder系统分析dbuilder面向的主要用户人群为web后台管理员以及开发人员,因此其系统分析过程,将更多的站在web后台管理员及开发人员的角度考虑问题。
2.1 需求分析项目需要实现如下几点核心功能。
1)        数据源管理
用户可以在界面为项目配置多个数据源。配置的数据源信息包括数据库类型、地址、数据库名、端口、用户名、密码等信息。支持对数据源的增删改查,保证对数据源的增删改查不轻易造成系统问题。
2)        代码生成
此功能是dbuilder的核心要实现的功能,用户在选择数据源和数据表之后,能够对数据库表的字段做简单配置,配置包括form表单配置、list(table)列表配置、关系配置、全局属性配置。配置完成后dbuilder要能生成对数据库表的crud的mvc代码,即需要实现crud可用功能,但不用编写代码。
3)        数据库表crud
生成的代码必须支持数据表记录的新建、删除、更新、查询操作。
4)        菜单管理
dbuilder要能将生成的代码跟一个菜单项绑定,让用户点击菜单项之后,就可以使用dbuilder生成的crud功能。此菜单必须包括后台菜单,前台菜单不是必须的。
5)        用户管理
用户要实现多种角色。必须能够以邮箱为用户唯一标识,并作为登录参数。未来还要实现支持qq、微信、新浪微博基于oauth2.0的互联登录。
6)        权限管理
dbuilder要能实现不同用户角色对不同crud代码的执行、访问权限做到三维的可配置。譬如,现有一个文章管理的crud功能模块,用户角色分为系统管理员(superadmin),管理员(admin),访客(guest),那么dbuilder要能实现如下的三维权限配置,且将之作为所有module的默认权限。
表2-1 module权限配置表
用户组与权限
查看
编辑
删除
导出
superadmin




admin



guest

7)        站点参数配置
dbuilder作为一个网站的web后台程序,对站点的全局参数配置也是必须的,这些参数包括网站名字、关键词、联系地址、友情链接等等。
8)        操作日志
dbuilder要记录用户的操作信息,包括访问的页面、执行的crud类型、时间等等信息。日志的记录形式支持数据库和文件两种方式。
9)        多语言支持
dbuilder要支持多国语言的切换。至少应该支持中文和英语两种语言,且以中文为默认。
10)    多数据库类型支持
dbuilder要支持多种类型数据库,暂时主要支持关系型数据库,包括mysql,ms sqlserver,oracle,postgresql等等。
2.2 数据原型分析按照需求提取可得实体有:用户、用户组、数据源、代码模块、菜单,关系有:权限、日志。实体与关系的含义如下:
用户:表示使用dbuilder的用户;用户组:表示用户的类型分组,用户类型应该至少包括访客、管理员、超级管理员三种;数据源:表示dbuilder包含的数据库配置,一个数据源的配置包含连接一个数据库所需的基本参数;代码模块:表示dbuilder生成的代码模块,描述了代码文件和配置;菜单:表示dbuilder的左侧菜单项;权限:表示用户组对每个代码模块的各种操作权限;日志:表示用户对每个代码模块的crud访问日志。实体与关系的er图如下:
图2-1 er图
2.3 原则性要求dbuilder应该要做成一套高性能、高可用的crud生成器,为此dbuilder设计中应该符合下面几项原则:
dbuilder要精确到每个数据库字段可配置;应具备一个web后台应用的雏形,使用户可在此基础上快速建立完整的web后台应用;dbuilder要尽可能减少sql操作,必要时可借助缓存、异步等技术,减少请求的处理逻辑,提高页面效率,减少用户等待时间;dbuilder要有美观、简洁、直观的用户界面;dbuilder要留有大量的扩展接口,能够让用户通过二次开发快速实现较为复杂的功能。第三章           dbuilder系统设计3.1 系统架构dbuilder有下面2个核心的构件core crud 模块和gmodule,gmodule对core crud 模块有继承依赖的关系,gmodule由mvc code和crud config组成;core crud模块是手工编写的代码,而gmodule是dbuilder生成的代码;core crud 模块实现crud操作,gmodule实现扩展功能。下图表示了这两个构件的组成和关系
图3-1概念与构件
下面对图中设计的概念、构件、模块关系以及build与crud流程做详细阐述。
3.1.1 core crud 模块core crud 模块实现核心crud操作,一切对gmodule mvc中controller的crud请求,最终转交至core crud 模块进行处理。core crud 模块会开放一些预处理和后处理接口交由gmodule实现,这些接口会在model,controller,view上都有体现。
core crud 模块主要包括如下文件
app/controllers/admin/admincontroller.phpapp/models/basemodel.phpapp/config/crud/admin.phpapp/views/admin/core/list.blade.phpapp/views/admin/core/form.blade.phpcore crud 模块读取gmodule configuration实现真正的crud操作。
3.1.2 gmodulegmodule(generated module)不但实现了core crud module接口(mvc代码),而且具有自己配置文件(crud configuration)。每一gmodule表示以一张数据库表为主表,具备crud功能的代码文件合集(包括对应的mvc + configuration代码)。譬如,dbuilder生成的一个gmodule, 主表为core数据源user表,名字为user,那么user gmodule应包含下面代码文件:
controllers/usercontroller.phpmodels/user.phpviews/user/_list.blade.phpviews/user/_form.blade.phpviews/user/view.blade.phpconfig/crud/user.php代码文件命名取决于gmodule的名字,故为保证生成的代码文件不冲突,取gmodule的名字(gmodule key,gmodule name)作为gmodule的唯一标识。每一个gmodule的信息都被保存在数据库中。一次新建 gmodule操作将会新建上述所有代码文件,更新相关文件,并插入一条gmodule记录到数据库。一次更新 gmodule操作将只会更新configuration文件。
gmodule 由mvc代码和crud configuration代码组成,下面分别进行阐述:
mvc代码:用来实现扩展接口。crud请求应最先路由到gmodule mvc的中的controller(控制器)。并且gmodule mvc 应与core crud module的mvc代码有继承关系。crud configuration代码:实现对gmodule主表增删改查参数的配置。该文件放置在app/config/crud/目录下,以php array的格式定义。它包含对所有字段的表单,列表,视图,关系等参数的配置,以及全局的参数配置。gmodule并不表示具体某一个模块,而是代指一类模块,这种模块可以由dbuilder生成,或者由开发人员手工建立。它主要用来实现core crud module的接口,主要包括下述几部分
1)        controller接口
假设gmodule模块的 controller为a,core crud module 的controller为b,则a应继承自b。crud请求会先路由到a,而实际的处理者是b。a会实现b开放的下列接口。
beforelistexcutequery(&querier):该接口在list查询器执行查询之前调用,传递的参数为查询器引用。用来在查询之前,绑定特殊的查询参数。beforelist(&data):该接口在list查询器执行之后,渲染list视图之前调用。传递的参数为视图参数引用,其中包括查询出的model集合。用来对查询的model 集合做后处理,或者对list视图绑定一些module专有的参数。beforeeditexcutequery(&querier):该接口在edit请求中model查询器执行查询之前调用,传递的是查询器引用。用来绑定查询model需要的特殊参数。beforeedit(&data):该接口在edit中model查询器执行之后,渲染视图之前调用,传递的是视图参数引用,其中包括查询器查询出的model。用来做渲染前的预处理。aftersave(&model):该接口在edit中,保存编辑的之后调用,传递的是保存在数据库中,最新的数据库记录持久化的model。用来对model做一些复杂的后级联处理。beforeview(data): 该接口在view请求中,view 查询器查询之后调用,传递的是视图参数的引用。用来对视图显示做预处理。2)        model 接口
gmodule mvc代码中的model也继承自basemodel,实现 basemodel类开放的一些接口可以完成扩展。
formatxxxattribute():该接口用来格式化某个字段。本产品基于laravel,其已经具备类似的接口,就是getxxxxattribute()。但这样的接口的优先级比字段优先级高,这在特殊的情况下为开发带来了不便,所以再设计一个类似的接口,该接口的优先级低于字段本身。
3)        view 接口
视图的扩展接口与前两者不同,主要体现在子视图与视图块上,也就是在core curd模块的视图基础上,扩展视图组件。默认core crud mvc视图生成的是一个表格或者一个表单,占满页面。而view接口将提供在该表格上下左右扩展页面组件的能力。
4)        configuration
每一个gmodule对应一个configuration文件,其中包含gmodule对主表各个字段的配置参数,以及布局参数。
3.1.3 模块关系crud请求路由到gmodule的controller,gmodule代码实现core crud mvc开放的接口,而由core crud module去真正实现对数据库的crud操作。每一个gmodule的信息应该被记录在数据库表中,以便给gmodule关联菜单,控制权限,记录操作日志等等。一些主要模块之间的关系如下图所示。
图3-2模块关系
从图2-2中可以看到,由gmodule管理模块根据用户配置来生成一个gmodule a,当用户的crud请求到达gmodule a时,gmodule 会讲请求转交core crud进行处理,core crud 模块再以sql对数据库进行crud操作。
3.1.4 build 与 crud流程dbuilder项目的方案,将真正的crud操作交给了core crud module去执行,crud参数由get或者post请求参数与gmodule configuration构成,而gmodule的mvc代码只是去实现core crud mvc开放的一些预处理或者后处理接口。
图2-3是dbuilder最核心的流程图,包含module的生成和处理crud请求的过程,图2-4是sximobuilder 中module的生成和处理crud请求的流程图。
图3-3 dbuilder 代码生成和处理crud的流程
图3-4 sximobuilder 代码生成和处理crud的流程
对比两者,可以看到两者的最大区别,是dbuilder复用一份crud代码,而不是像sximo那样为每一个module生成一套可以当独执行的crud代码。这样做的好处是提高了复用性,并通过module crud mvc实现预处理/后处理接口达到扩展性的目的。
3.2 core数据源core数据源是dbuilder的默认数据源,其类型为mysql,数据库名为dbuilder,本节按照《数据原型分析》一节进行详细的数据库设计。为提高程序性能,数据源信息保存在代码文件app/config/datasource.php中,文件内容如下:
array (
            'driver' => 'mysql',
            'host' => 'localhost',
            'database' => 'dbuilder',
            'username' => 'root',
            'password' => 'root',
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix' => '',
            'edit' => false,
            'port' => 3306,
        ),
        // more data source
 );
其中core数据源有下述数据表:
1)        d_menu 表:表示后台左侧树形菜单,每一个可点击跳转的菜单项必须与一个module进行关联。
表3-1 web后台左侧菜单表
field
type
default
info
id
int
auto_increment
pri
module_id
int
module_name
varchar(12)
parent_id
null
父菜单项
title
varchar(12)
module_title
显示名称
_order
int
0
排序字段
2)        d_module 表:记录了module信息,每一条d_module表的记录代表了dbuilder生成的一个module。
表3-2 module信息描述
field
type
default
info
id
int
auto_increment
pri
name
varchar(32)
uin
title
varchar(32)
module标题
note
varchar(32)
module 说明
db_source
varchar(16)
core
数据源名称
db_table
varchar(16)
module主表
db_table_key
varchar(16)
主表pri
3)        d_user 表:保存着使用后台程序的用户。
表3-3 web后台用户
field
type
default
info
id
int
auto_increment
pri
username
varhcar(64)
用户名
email
varchar(64)
邮箱
password
varchar(64)
hash
salt
varchar(64)

last_login
timestamp
最后登录时间
remember_token
记住密码口令
group_id
int
组id
4)        d_group表:表示对后台用户的分组信息。
表3-4 用户分组表
field
type
default
info
id
int
auto_increment
pri
name
varhcar(64)
组名
note
varchar(128)
组说明
level
int
组级别
5)        d_group_access表:记录了每个gmodule、不同后台用户组与各种操作权限的三维权限信息。
表3-5 用户组对module权限表
field
type
default
info
id
int
auto_increment
pri
group_id
int
组id
module_id
int
module模块id
edit
int
1
可编辑
view
int
1
可查看
delete
int
1
可删除
export
int
1
可导出
6)        d_log表:记录了每个用户的操作日志。
表3-6 用户操作日志
field
type
default
info
id
int
auto_increment
pri
user_id
int
用户id
ip_addr
varchar(15)
客户端ip
module_id
int
访问的moduleid
module_title
varchar(16)
task
varchar(16)
操作
created_at
timestamp
可导出
3.3 数据源管理模块dbuilder需要支持多数据源,多种类型数据库。数据源信息保存在d_database表中。考虑到数据库操作是频繁操作,如果将数据源信息保存在数据库中,则每次数据库操作将多一次数据源查询操作,这样做浪费性能。那么dbuilder不应该把数据源信息保存在数据库中,而应该保存在代码文件中。数据源管理的信息包括数据源名称(数据源的唯一标识,dbuilder默认的数据源名为core)、数据库类型、地址、端口、数据库名、用户名、密码等等信息。因为数据源管理模块并不对表进行增删改查操作,所以数据源管理模块并不是一个gmodule模块。该模块的代码完全手工编写。
3.4 gmodule 管理模块dbuilder将以基于名字为“module”的gmodule作为生成gmodule的用户接口,该模块称作gmodule管理模块,换言之gmodule管理模块本身就是一个gmodule,该gmodule的主表即是core数据源中保存gmodule信息的数据库表,改gmodule的名字为“module”。gmodule 管理模块包含创建,更新和删除gmodule 的所有代码文件以及数据库记录。gmodule的新建和删除需要更新全局的gmodule路由。
1)        gmodule 路由
gmodule路由定义在一个独立的代码文件中,为一个以gmodule名字进行减号分词并全部小写的字符串为键(譬如:gmodule名字为orderitem,则键值为order-item)、以module中controller类的类名为值的map字典,gmodule路由是全局的。
2)        gmodule 新建&更新
新建gmodule将在数据库中生成一条记录、生成所有的module文件、并更新路由。更新操作只修改配置文件。新建与更新都使用相同的编辑视图,此编辑视图是对gmodule configuration的图形化配置界面。
3)        gmodule 删除
gmodule删除将删除所有的gmodule mvc代码,删除gmodule configuration代码,删除数据库表记录,并更新gmodule路由。
3.5 core crud 模块core crud 模块是dbuilder处理crud请求的实际处理者,它由下述几部分组成:
1)        参数解析初始化
初始化model,实例化一个module的model对象作为初始化查询器。加载module configuration,对未设置的值进行设置默认值,对参数进行汇聚。
2)        表单form
主要包括新建和更新功能。根据gmodule主表主键primarykey是否设置判断是新建还是更新操作。下图是form模块的流程
图3-5 form执行流程
form 分两部分,第一部分渲染form页面给用户填写。第二部分为form保存。
渲染form页面需要考虑的有form控件和有外键关系的字段要怎么处理。form控件需要支持类型包括text、text_date、text_datetime、textarea、select、radio、checkbox、file、hidden、address以及custom,自定义控件应该继承formcontrol类,自定义控件的渲染由控件的render方法完成。form渲染需要判断有关系的字段做辅助加载。比如对post(文章)表进行编辑,post表有一个字段为category_id,表示文章的栏目id,对应category(栏目)表的id字段。这时需要对category_id使用select,radio,checkbox控件进行加载,方便用户输入。比如使用select控件,那么应该将category.id作为option的value,将category.name作为option中的text。这样做也是为了方便用户输入。此步骤与list中搜索时有共性,因此代码可复用。
form 保存需要考虑一些自定义控件的保存,自定义控件的数保存由自定义控件类的onsave方法完成。form 保存还需要考虑关系的保存,默认应该级联更新附属表。form 表单在用户输入完成点击保存之后,要分下面几步:
根据字段配置的验证规则进行验证;应判断module configuration 中的relation进行分析,进行必要的级联操作;并要调用自定义控件的onsave方法;最后才应更新或新建主表数据;跳转:更新或新建成功跳转至list,失败跳转至form。form 还需要开放对应的预处理和后处理接口。
3)        列表list(table)
list是一个分页table,按照module configuration 中的字段配置显示分页数据。支持列表搜索,排序,勾选删除,导出等功能;
分页展现数据以initquerier模块得到的model作为查询器,结合分页,查询出基本的数据列表。分页类型为全页刷新类型(非异步分页);list搜索:支持在module configuration中定义了search不等于false的字段作为搜索条件。搜索关系为逻辑与的关系。并反映在get参数上。搜索输入控件根据字段的form type来定。在form 中定义为select,radio,checkbox控件的字段,在list中都将使用select控件作为输入控件;list 排序:以在module configuration中定义了form.sort 不等于 false的字段作为可排序字段。排序只支持按单一字段排序,降序方式含升序和降序;list 多选操作主要支持多选删除,多选复制操作,任何删除操作都需确认;list 数据每行记录的支持的操作按module configuration中的配置给出,默认支持编辑,删除,查看三项操作;list 也要开放预处理/后处理接口给module crud mvc。4)        查看view
view 暂时以form为基础,提供预处理后处理接口,但不允许编辑。
第四章           dbuilder系统实现4.1 目录结构代码按照前段资源、mvc、configuration、library等概念进行了分目录存放。下面表格中给出了主要目录的说明:
表4-2 代码主要目录
目录
作用
assets
此目录存放着各种各样的前端资源。包括bootstrap,以及自定义的css和js文件。
plugins
存放特殊前端插件的目录,比如富文本编辑器,视音频插件等等。
app/controllers/admin
存放着mvc中控制器的目录。其中,dbuilder的核心在admin目录下。
app/models
存放着mvc中模型(model)的目录。用来做数据库查询用。
app/views
存放着mvc中视图的目录。文件名以*.blade.php的格式命名。
app/library
存放php辅助类,php库的目录。
app/config/crud
存放module configuration的目录。
4.2 gmodule 配置文件gmodule配置文件定义了gmodule的参数,该文件保存在app/config/crud/下,是以gmodule name进行蛇形分词得到的字符串命名的php文件(譬如:一gmodule的名字为orderitem,则gmodule配置文件为order_item.php)。配置参数以数组格式返回。
考虑到php数组在表格中呈现的美观性,对参数以配置中的key=>value形式,以点分形式key.value表示。
表4-3 root配置
configuration key
类型
默认值
含义
fields
array
array()
字段列表
fields.field_name
array
array()
对field_name字段的配置
fields.field_name.label
string
up(field_name)
显示在列表表格的表头的内容,和form控件旁边的内容
fields.field_name.form
array
array()
field_name字段的表单配置,具体参考
fields.field_name.form配置
fields.field_name.list
array
array()
field_name 字段的列表配置,具体参考
fields.field_name.list配置
fields.field_name. relation
array
array()
field_name 字段的关系
表4-3中每个字段的表单配置说明如下表所示:
表4-4 fields.field_name.form配置
configuration key
值类型
默认
含义
type
string
text
form控件类型
show
bool
true
是否出现在表单
hidden
bool
false
是否以隐藏的空间在表单中
rule
string
required
验证规则
ajax_validate
bool
false
是否异步验证
placeholder
string
控件中的提示
表4-3中每个字段的列表配置说明如下表所示:
表4-5 fields.field_name.list配置
configuration key
值类型
默认
含义
show
bool
true
是否出现在表单
sort
bool
true
字段是否可以排序,默认可排序
search
bool,array
array()
是否可搜索以及搜索规则
string
控件中的提示
表4-3中每个字段的关系配置说明如下表所示:
表4-6 fields.field_name.relation配置
configuration key
值类型
默认
含义
table
string
关联表
foreign_key
string
id
对应关联表里的字段
show
string
关联表里的一个字段,当需要转义时,将用该字段代替field_nae字段显示
as
string
table_show
转义查询出的值用哪个字段表示,主要为了防止主表和关联表有重复字段
下面是一个名为post的gmodule的configuration文件
1 'core', 3 'table' => 'post', 4 'fields' => 5 array ( 6 'id' => 7 array ( 8 'label' => 'id', 9 'form' => 10 array ( 11 'show' => true, 12 'hidden' => true, 13 'type' => 'text', 14 'rule' => 'required', 15 'ajax_validate' => false, 16 'placeholder' => '', 17 ), 18 'list' => 19 array ( 20 'show' => true, 21 'sort' => true, 22 'search' => '=', 23 'lookup' => false, 24 ), 25 'relation' => 26 array ( 27 'type' => '', 28 'table' => '', 29 'foreign_key' => '', 30 'show' => '', 31 'as' => '', 32 ), 33 ), 34 'title' => 35 array ( 36 'label' => '标题', 37 'form' => 38 array ( 39 'show' => true, 40 'hidden' => false, 41 'type' => 'text', 42 'rule' => 'required', 43 'ajax_validate' => false, 44 'placeholder' => '', 45 ), 46 'list' => 47 array ( 48 'show' => true, 49 'sort' => true, 50 'search' => '=', 51 'lookup' => false, 52 ), 53 'relation' => 54 array ( 55 'type' => '', 56 'table' => '', 57 'foreign_key' => '', 58 'show' => '', 59 'as' => '', 60 ), 61 ), 62 'short' => 63 array ( 64 'label' => '摘要', 65 'form' => 66 array ( 67 'show' => true, 68 'hidden' => false, 69 'type' => 'textarea', 70 'rule' => 'required', 71 'ajax_validate' => false, 72 'placeholder' => '', 73 ), 74 'list' => 75 array ( 76 'show' => true, 77 'sort' => true, 78 'search' => '=', 79 'lookup' => false, 80 ), 81 'relation' => 82 array ( 83 'type' => '', 84 'table' => 'category', 85 'foreign_key' => 'id', 86 'show' => 'id', 87 'as' => '', 88 ), 89 ), 90 'content' => 91 array ( 92 'label' => '正文', 93 'form' => 94 array ( 95 'show' => true, 96 'hidden' => false, 97 'type' => 'wysiwyg', 98 'rule' => 'required', 99 'ajax_validate' => false,100 'placeholder' => '',101 ),102 'list' => 103 array (104 'show' => false,105 'sort' => true,106 'search' => '=',107 'lookup' => false,108 ),109 'relation' => 110 array (111 'type' => '',112 'table' => 'category',113 'foreign_key' => 'id',114 'show' => 'id',115 'as' => '',116 ),117 ),118 'view_ct' => 119 array (120 'label' => '查看次数',121 'form' => 122 array (123 'show' => false,124 'hidden' => false,125 'type' => 'text',126 'rule' => 'required',127 'ajax_validate' => false,128 'placeholder' => '',129 ),130 'list' => 131 array (132 'show' => true,133 'sort' => true,134 'search' => '=',135 'lookup' => false,136 ),137 'relation' => 138 array (139 'type' => '',140 'table' => '',141 'foreign_key' => '',142 'show' => '',143 'as' => '',144 ),145 ),146 'created_at' => 147 array (148 'label' => '创建时间',149 'form' => 150 array (151 'show' => false,152 'hidden' => false,153 'type' => 'text',154 'rule' => 'required',155 'ajax_validate' => false,156 'placeholder' => '',157 ),158 'list' => 159 array (160 'show' => false,161 'sort' => true,162 'search' => '=',163 'lookup' => false,164 ),165 'relation' => 166 array (167 'type' => '',168 'table' => '',169 'foreign_key' => '',170 'show' => '',171 'as' => '',172 ),173 ),174 'updated_at' => 175 array (176 'label' => '更新时间',177 'form' => 178 array (179 'show' => false,180 'hidden' => false,181 'type' => 'text',182 'rule' => 'required',183 'ajax_validate' => false,184 'placeholder' => '',185 ),186 'list' => 187 array (188 'show' => true,189 'sort' => true,190 'search' => '=',191 'lookup' => false,192 ),193 'relation' => 194 array (195 'type' => '',196 'table' => '',197 'foreign_key' => '',198 'show' => '',199 'as' => '',200 ),201 ),202 'category_id' => 203 array (204 'label' => '栏目',205 'form' => 206 array (207 'show' => true,208 'hidden' => false,209 'type' => 'select',210 'rule' => 'required',211 'ajax_validate' => false,212 'placeholder' => '',213 ),214 'list' => 215 array (216 'show' => true,217 'sort' => true,218 'search' => '=',219 'lookup' => false,220 ),221 'relation' => 222 array (223 'type' => 'belongsto',224 'table' => 'category',225 'foreign_key' => 'id',226 'show' => 'title',227 'as' => 'category_title',228 ),229 ),230 ),231 'list_options' => 232 array (233 'page' => 10,234 'create' => true,235 'update' => true,236 'delete' => true,237 ),238 'form_options' => 239 array (240 'layout' => 241 array (242 'cols' => 12,243 'label_cols' => 1,244 'input_cols' => 11,245 ),246 ),247 'relations' => 248 array (249 'id' => 250 array (251 'type' => '',252 'table' => '',253 'foreign_key' => '',254 'show' => '',255 'as' => '',256 ),257 'title' => 258 array (259 'type' => '',260 'table' => '',261 'foreign_key' => '',262 'show' => '',263 'as' => '',264 ),265 'short' => 266 array (267 'type' => '',268 'table' => '',269 'foreign_key' => '',270 'show' => '',271 'as' => '',272 ),273 'content' => 274 array (275 'type' => '',276 'table' => '',277 'foreign_key' => '',278 'show' => '',279 'as' => '',280 ),281 'view_ct' => 282 array (283 'type' => '',284 'table' => '',285 'foreign_key' => '',286 'show' => '',
其它类似信息

推荐信息