dbschema 数据库表定义文件

在ecos框架前,我们使用PowerDesigner来管理这些表结构,但是在一些项目的版本管理过程中,有时需要维护多个版本。powerdesigner的储存文件为一个单一的巨大的xml格式pdm文件。 这在进行版本的合并分支时几乎无法处理。 而在ecos,我们使用php去描述表结构有了以下几个优势:

  • 数据库定义具有版本管理特性
    • 各分支开发互不干扰
    • 协同更改时,可以进行合并操作
    • 针对单表的版本还原与操作日志
    • 容易做自动化的表结构对比
  • 按照用途来定义字段类型,不会出现同一种数据类型而字段定义不一致的情况
  • 简单的外键实现,方便的统计表的依赖关系,使得外键字段定义完全一致
  • 作为数据抽象层, 我们可以更用以
  • app 更容易扩展独立的表
  • 将数据库特性进行包装, 可以统一设定, 数据库版本 type = MyISAM DEFAULT CHARACTER SET语法 等

dbschema 是什么

我们先看一下base/dbschema/apps.php 文件

可以将注释中间的代码去掉 注释中间的代码和desktop app相关

<?php
$db
['apps']=array (
    
'columns' =>
        array (
            
'app_id' => array(
                
'type' => 'varchar(32)',
                
'required' => true,
                
'default' => '',
                
'pkey' => true,
                
// begin 和desktop相关 ----------------------
                
'width' => 100,
                
'label' => app::get('base')->_('程序目录'),
                
'hidden' => 1,
                
'editable' => false,
                
'in_list' => true,
                
'default_in_list' => false,
                
// end --------------------------------------
            
),
            
'app_name' => array(
                
'type' => 'varchar(50)',
                
// begin 和desktop相关 ----------------------
                
'width' => 150,
                
'label' => app::get('base')->_('应用程序'),
                
'is_title'=>1//在链接表中显示的字段
                
'in_list' => true,
                
'default_in_list' => 1
                
// end --------------------------------------
            
),
            
'debug_mode' => array(
                
'type' => 'bool',
                
'default' => 'false',
                 
// begin 和desktop相关 ----------------------
                
'width' => 100,
                
'label' => app::get('base')->_('调试模式'),
                
'in_list' => true,
                
'default_in_list' => false
                
// end --------------------------------------
            
),
            
'app_config' => array(
                
'type' => 'text'
            
),
            
'status' =>  array(
                
'type' => array (
                    
'installed' => app::get('base')->_('已安装, 未启动'),
                    
'resolved' => app::get('base')->_('已配置'),
                    
'starting' => app::get('base')->_('正在启动'),
                    
'active' => app::get('base')->_('运行中'),
                    
'stopping' => app::get('base')->_('正在关闭'),
                    
'uninstalled' => app::get('base')->_('尚未安装'),
                    
'broken' => app::get('base')->_('已损坏'),
                ),
                
// begin 和desktop相关 ----------------------
                
'label' => app::get('base')->_('状态'),
                
'width' => 100,
                
'default' => 'uninstalled',
                
'in_list' => true,
                
'default_in_list' => true,
                
// end --------------------------------------
            
),
            
'webpath'=> array(
                
'type'=>'varchar(20)'
            
),
            
'description'=> array(
                
'type'=>'varchar(255)',
                
// begin 和desktop相关 ----------------------
                
'width' => 300,
                
'label' => app::get('base')->_('说明'),
                
'in_list' => true,
                
'default_in_list' => 1
                
// end --------------------------------------
            
),
            
'local_ver'=> array(
                
'type'=>'varchar(20)',
                
// begin 和desktop相关 ----------------------
                
'width' => 100,
                
'label' => app::get('base')->_('当前版本'),
                
'in_list' => true,
                
'default_in_list' => 1
                
// end --------------------------------------
            
),
            
'remote_ver'=> array(
                
'type'=>'varchar(20)',
                
// begin 和desktop相关 ----------------------
                
'width' => 100,
                
'label' => app::get('base')->_('最新版本'),
                
'in_list' => true,
                
'default_in_list' => false
                
// end --------------------------------------
            
),
            
'author_name'=> array(
                
'type'=>'varchar(100)'
            
),
            
'author_url'=> array(
                
'type'=>'varchar(100)'
            
),
            
'author_email'=> array(
                
'type'=>'varchar(100)'
            
),
            
'dbver'=> array(
                
'type'=>'varchar(32)'
            
),
            
'remote_config'=> array(
                
'type'=>'serialize'
            
)
        ),
    
'version' => '$Rev: 44008 $',
    
'unbackup' => true,
);
?>

这个就是以上代码经过解析后生成的sql语句

CREATE TABLE `sdb_base_apps` (
	`app_id` varchar(32) not null default '',
	`app_name` varchar(50),
	`debug_mode` enum('true','false') default 'false',
	`app_config` text,
	`status` enum('installed','resolved','starting','active','stopping','uninstalled','broken') default 'uninstalled',
	`webpath` varchar(20),
	`description` varchar(255),
	`local_ver` varchar(20),
	`remote_ver` varchar(20),
	`author_name` varchar(100),
	`author_url` varchar(100),
	`author_email` varchar(100),
	`dbver` varchar(32),
	`remote_config` longtext,
	primary key (app_id)
)ENGINE = MyISAM DEFAULT CHARACTER SET utf8;

dbschema文件有几个重要的功能

1. 描述表结构

2. 定义desktop app的列表项

用dbschema来描述表结构

ecos安装时,会扫描相关app中的dbschema中的文件,用这个文件生成相应的表结构并创建

约定:

    文件名 apps.php 对应于 $db['apps'] 生成的表名为 [prefix]_[appname]_apps
       如: 表前缀: sdb
           文件: base/dbschemma/apps.php
           生成的表名为 sdb_base_apps
           与之对应的model为  base_mdl_apps

columns

表字段

<?php
'columns' => array(
    
'ref_id' => array(          // 字段名称
        
'type' => 'int(8)',     // 字段类型
        
'required' => true,     // 不能为空 默认为false
        
'pkey' => true,         // 是否是主键 默认为false
        
'label' => 'id',
        
'editable' => false,
        
'extra' => 'auto_increment'// 自增
    
),
    
'goods_id' => array(
        
'type' => 'table:goods',  // 对应用于同一app下goods表中的主键类型
        
'default' => 0,           // 默认值
        
'required' => true,
        
'editable' => false,
    ),
    
'status' =>  array(
        
'default' => 'uninstalled',
        
'type' => array (  // 生成枚举类型 enum('installed','resolved','starting'....)
            
'installed' => app::get('base')->_('已安装, 未启动'),
            
'resolved' => app::get('base')->_('已配置'),
            
'starting' => app::get('base')->_('正在启动'),
            
'active' => app::get('base')->_('运行中'),
            
'stopping' => app::get('base')->_('正在关闭'),
            
'uninstalled' => app::get('base')->_('尚未安装'),
            
'broken' => app::get('base')->_('已损坏'),
        ),
        
'label' => app::get('base')->_('状态'),
        
'width' => 100,
        
'in_list' => true,
        
'default_in_list' => true,
   )
)
?>

字段名称

字段名称就是键值

<?php
'columns' => array(
    
'goods_id' => array(),
)

sdf

type

1 mysql字段类型

<?php
'author_name'=> array(
    
'type'=>'varchar(100)'
)
?>
生成的语句是 `author_name` varchar(100),

还有 int(n),varchar(n),text,等mysql字段的类型

2 枚举类型

<?php
'status' =>  array(
    
'default' => 'uninstalled',
    
'type' => array (  // 生成枚举类型 enum('installed','resolved','starting'....)
        
'installed' => app::get('base')->_('已安装, 未启动'),
        
'resolved' => app::get('base')->_('已配置'),
        
'starting' => app::get('base')->_('正在启动'),
        
'active' => app::get('base')->_('运行中'),
        
'stopping' => app::get('base')->_('正在关闭'),
        
'uninstalled' => app::get('base')->_('尚未安装'),
        
'broken' => app::get('base')->_('已损坏'),
)
?>
将生成的sql语句 `status` enum('installed','resolved','starting','active','stopping','uninstalled','broken') default 'uninstalled',

desktop中的高级搜索将产生一个select选项可以进行选择

3 money

<?php
'price' =>  array(
    
'default' => '0.00',
    
'type' => 'money'
)
?>
将生成的sql语句 'price' decimal(20,3) default 0.00

涉及到金额类的可以直接使用这个,你还在犹豫什么呢

使用dbeav的save时会验证是否是money类型的数据 如果不是将抛出异常

4 email

<?php
'email' =>  array(
    
'type' => 'email'
)
?>
将生成的sql语句 'email' varchar(255)

使用dbeav的save时会验证是否是email类型的数据 如果不是将抛出异常

5 bn

<?php
'bn' =>  array(
    
'type' => 'bn'
)
?>
将生成的sql语句 'bn' varchar(255)

商品的货号 货品的货号,订单项的货号等等是使用的这个 便于理解

6 html

<?php
'content' =>  array(
    
'type' => 'html'
)
?>
将生成的sql语句 'content' text

商品详情 文章内容等等是使用的这个 一下就知道这个是使用编辑器处理的数据 便于理解

7 bool

<?php
'disabled' =>  array(
    
'default'=>'false'
    'type' 
=> 'bool'
)
?>
将生成的sql语句 'disabled' enum('true','false') default 'false'

一般一些开关类型的字段可以选这种类型

8 time

<?php
'create_time' =>  array(
    
'type' => 'time'
)
?>
将生成的sql语句 'create_time' int(10) unsigned

存储时间类的类型 在desktop的高级搜索里绑定日历

9 cdate

<?php
'create_time' =>  array(
    
'type' => 'cdate'
)
?>
将生成的sql语句 'create_time' int(10) unsigned

和 time的区别在于 在desktop的高级搜索里没有绑定日历,一般不用于高级搜索

10 intbool

<?php
'is_open' =>  array(
    
'default'=>'0'
    'type' 
=> 'intbool'
)
?>
将生成的sql语句 'is_open' enum('0','1') default '0'

和bool类型区别不大 个人习惯问题 一般一些开关类型的字段可以选这种类型

11 region

<?php
'area' =>  array(
    
'type' => 'region'
)
?>
将生成的sql语句 'area' varchar(255)

12 password

<?php
'passwd' =>  array(
    
'type' => 'password'
)
?>
将生成的sql语句 'passwd' varchar(32)

一般存储密码的字段 一般是md5加密后的字符 便于理解

13 tinybool

<?php
'is_open' =>  array(
    
'default'=>'N'
    'type' 
=> 'tinybool'
)
?>
将生成的sql语句 'is_open' enum('N','Y') default 'N'

和intbool,bool类型区别不大 个人习惯问题 一般一些开关类型的字段可以选这种类型

14 number

<?php
'nums' =>  array(
    
'type' => 'number'
)
?>
将生成的sql语句 'nums' mediumint unsigned

一般用于数量等类型

15 float

<?php
'rate' =>  array(
    
'type' => 'float'
)
?>
将生成的sql语句 'rate' float

16 gender

<?php
'sex' =>  array(
    
'type' => 'gender'
)
?>
将生成的sql语句 'sex' enum('male','false') NULL

用于会员性别

17 ipaddr

<?php
'ip' =>  array(
    
'type' => 'ipaddr'
)
?>
将生成的sql语句 'ip' varchar(20)

ip地址 便于理解

18 serialize

<?php
'config' =>  array(
    
'type' => 'serialize'
)
?>
将生成的sql语句 'config' longtext

一般使用此类型的字段 在使用dbeav的save 时传入的数据是一个数组保存时将以系列化形式保存入库在使用dbeav的dump时此类型字段将从数据库取出后反系列化后返回

19 last_modify

<?php
'update_time' =>  array(
    
'type' => 'last_modify'
)
?>
将生成的sql语句 'update_time' int(10) unsigned

和time类型相似 只是名称可以理解成 最后更新时间

20 关联表主键

<?php
'type_id' =>  array(
    
'type' => 'table:table_name'
)
?>
将本app下的table_name这个表的关键字作为关联关系

在desktop的高级搜索里这个字段会取出所有相关的数据

required

是否必填 必填:true, 可以不填:false(默认)mysql中的" not null "

default

默认值mysql中的" default null "

pkey

是否是主键 是:true, 否:false(默认)mysql中的" primary key (app_id) "

extra

扩展值(可以这什么说吧)

'extra' => 'auto_increment' mysql中的 " AUTO_INCREMENT "

'extra' => 'CHARACTER SET "utf8"' mysql中的 " CHARACTER SET 'utf8' "

index

索引 默认为空

以下是mysql创建索引的语法说明

CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
    [index_type]
    ON tbl_name (index_col_name,...)
[index_type]

index_col_name:
    col_name [(length)] [ASC | DESC]

index_type:
    USING {BTREE | HASH | RTREE}
在dbschema上的设置索引
<?php
'index' => array (
    
'ind_prefix' => array( // 索引名称
        
'columns' => array( // 要创建索引的数据库字段名
            
=> 'prefix',
        ),
        
'prefix' => '' // 索引的类型 UNIQUE|FULLTEXT|SPATIAL 如果为空 为一般的索引
        
'type' => '' // 指定索引算法 BTREE | HASH | RTREE
    
)
)
?>

version

版本号

<?php
'version' => '$Rev: 44008 $'
?>

unbackup

是否备份 true:不备份, false:备份(默认)

<?php
'unbackup' => true
?>

ignore_cache

是否缓存 true:不缓存, false:缓存(默认)

<?php
'ignore_cache' => true
?>

engine

mysql引擎 如果没有指定 为mysql默认设置

<?php
'engine' => 'innodb'
?>

comment

表描述

<?php
'comment' => app::get('b2c')->_('商品规格索引表')
?>

用dbschema来定义 desktop的列表

1 label

<?php
'label' => app::get('b2c')->_('分类')
?>


2 width

<?php
'width' => "150"
?>

定义desktop列表中本列的初始宽度

3 editable(已弃用)

<?php
'editable' => true
?>

定义在desktop列表中本列数据数据是否能进行编辑

是否在列表上进行编辑 true:可以 false:不可以(默认)

4 in_list

<?php
'in_list' => true
?>

定义在desktop列表中是否显示 true:是 false:否(默认)

5 default_in_list

<?php
'default_in_list' => true
?>

默认在desktop列表中是否显示 true:是 false:否(默认)如果有相关列表项配置 按配置显示

6 filterdefault

<?php
'filterdefault' => true
?>

默认在desktop高级搜索中是否默认显示 true:是 false:否(默认)如果有相关搜索项配置 按配置显示

7 filtertype,filtercustom

<?php
'filtertype' => 'normal' // normal按type的来生成过滤  custom 按dbschema中设定的filtercustom 设置过滤
?>

8 searchtype

列表页中简单搜索的处理方式,如果dbschema中存在searchtype则会在desktop列表上显示相关的简单搜索

如果searchtype=>则默认为'nequal'

以下是相关代码段自己慢慢理解

<?php
'than'=>' > '.$var,
'lthan'=>' < '.$var,
'nequal'=>' = \''.$var.'\'',
'noequal'=>' <> \''.$var.'\'',
'tequal'=>' = \''.$var.'\'',
'sthan'=>' <= '.$var,
'bthan'=>' >= '.$var,
'has'=>' like \'%'.$var.'%\'',
'head'=>' like \''.$var.'%\'',
'foot'=>' like \'%'.$var.'\'',
'nohas'=>' not like \'%'.$var.'%\'',
'between'=>' {field}>='.$var[0].' and '.' {field}<'.$var[1],
'in' =>" in ('".implode("','",(array)$var)."') ",
?>

9 is_title(2011-04-28:sunjinrong)

该属性的意义为是否为链接显示字段,true(是) false(否),不设置该属性默认为false。注意:该属性为唯一性属性,将多个字段设置为该属性时,会默认显示第一个设置字段。如果被链接的表没有一个字段被设置为,'is_title'=>true,则默认情况会显示该表主键的下一个字段。

bryant写的部分

数据库抽象层dbschema(bryant)

在ecos框架前,我们使用powerdesigner来管理这些表结构,但是在一些项目的版本管理过程中,有时需要维护多个版本。powerdesigner的储存文件为一个单一的巨大的xml格式pdm文件。 这在进行版本的合并分支时几乎无法处理。 而在ecos,我们使用php去描述表结构有了以下几个优势:

<?php
$db
['table_name'] = array(
    
'columns'=>array(
        
'col_1'=>array(
        
'type'=>'int',
            
'pkey'=>true,'comment'=>'id字段'), //主键
        
'col_p1'=>array('type'=>'int',
            
'pkey'=>true,'comment'=>'主键2'),   //联合主键
        
'col_33'=>array('type'=>'mediumint unsigned'),
        
//当然也支持通常的type
        
'col_2'=>array('type'=>'email',
            
'comment'=>'id字段'),  //email = varchar(255)
        
'col_3'=>array('type'=>'money',
            
'notnull'=>true,'default'=>3),
        
//money = decimal(20,3), 非空字段,默认为3.000
        
'col_4'=>array('type'=>'html',
            
'comment'=>'id字段'),   //html = text
        
'col_4'=>array('type'=>'bool',
            
'comment'=>'id字段'),   //bool = enum('true','false')
        
'table2_c1'=>array('type'=>'table_2:c1',
            
'comment'=>'表table_2的c1字段'),
        
//类型和table_2的c1字段相同, 当外键处理,自动加索引
    
),
    
'index'=>array(
        
'...',//再定义
    
)
    
'engine'=>'heap'//可不填,默认为myisam
    
'option'=>''//其他扩展语法
);