在ecos框架前,我们使用PowerDesigner来管理这些表结构,但是在一些项目的版本管理过程中,有时需要维护多个版本。powerdesigner的储存文件为一个单一的巨大的xml格式pdm文件。 这在进行版本的合并分支时几乎无法处理。 而在ecos,我们使用php去描述表结构有了以下几个优势:
我们先看一下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的列表项
在ecos安装时,会扫描相关app中的dbschema中的文件,用这个文件生成相应的表结构并创建
约定:
    文件名 apps.php 对应于 $db['apps'] 生成的表名为 [prefix]_[appname]_apps
       如: 表前缀: sdb
           文件: base/dbschemma/apps.php
           生成的表名为 sdb_base_apps
           与之对应的model为  base_mdl_apps
表字段
<?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(),
)
1 mysql字段类型
<?php
'author_name'=> array(
    'type'=>'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')->_('已损坏'),
)
?>
在desktop中的高级搜索将产生一个select选项可以进行选择
3 money
<?php
'price' =>  array(
    'default' => '0.00',
    'type' => 'money'
)
?>
涉及到金额类的可以直接使用这个,你还在犹豫什么呢
使用dbeav的save时会验证是否是money类型的数据 如果不是将抛出异常
4 email
<?php
'email' =>  array(
    'type' => 'email'
)
?>
使用dbeav的save时会验证是否是email类型的数据 如果不是将抛出异常
5 bn
<?php
'bn' =>  array(
    'type' => 'bn'
)
?>
商品的货号 货品的货号,订单项的货号等等是使用的这个 便于理解
6 html
<?php
'content' =>  array(
    'type' => 'html'
)
?>
商品详情 文章内容等等是使用的这个 一下就知道这个是使用编辑器处理的数据 便于理解
7 bool
<?php
'disabled' =>  array(
    'default'=>'false'
    'type' => 'bool'
)
?>
一般一些开关类型的字段可以选这种类型
8 time
<?php
'create_time' =>  array(
    'type' => 'time'
)
?>
存储时间类的类型 在desktop的高级搜索里绑定日历
9 cdate
<?php
'create_time' =>  array(
    'type' => 'cdate'
)
?>
和 time的区别在于 在desktop的高级搜索里没有绑定日历,一般不用于高级搜索
10 intbool
<?php
'is_open' =>  array(
    'default'=>'0'
    'type' => 'intbool'
)
?>
和bool类型区别不大 个人习惯问题 一般一些开关类型的字段可以选这种类型
11 region
<?php
'area' =>  array(
    'type' => 'region'
)
?>
12 password
<?php
'passwd' =>  array(
    'type' => 'password'
)
?>
一般存储密码的字段 一般是md5加密后的字符 便于理解
13 tinybool
<?php
'is_open' =>  array(
    'default'=>'N'
    'type' => 'tinybool'
)
?>
和intbool,bool类型区别不大 个人习惯问题 一般一些开关类型的字段可以选这种类型
14 number
<?php
'nums' =>  array(
    'type' => 'number'
)
?>
一般用于数量等类型
15 float
<?php
'rate' =>  array(
    'type' => 'float'
)
?>
16 gender
<?php
'sex' =>  array(
    'type' => 'gender'
)
?>
用于会员性别
17 ipaddr
<?php
'ip' =>  array(
    'type' => 'ipaddr'
)
?>
ip地址 便于理解
18 serialize
<?php
'config' =>  array(
    'type' => 'serialize'
)
?>
一般使用此类型的字段 在使用dbeav的save 时传入的数据是一个数组保存时将以系列化形式保存入库在使用dbeav的dump时此类型字段将从数据库取出后反系列化后返回
19 last_modify
<?php
'update_time' =>  array(
    'type' => 'last_modify'
)
?>
和time类型相似 只是名称可以理解成 最后更新时间
20 关联表主键
<?php
'type_id' =>  array(
    'type' => 'table:table_name'
)
?>
在desktop的高级搜索里这个字段会取出所有相关的数据
是否必填 必填:true, 可以不填:false(默认)mysql中的" not null "
默认值mysql中的" default null "
是否是主键 是:true, 否:false(默认)mysql中的" primary key (app_id) "
扩展值(可以这什么说吧)
'extra' => 'auto_increment' mysql中的 " AUTO_INCREMENT "
'extra' => 'CHARACTER SET "utf8"' mysql中的 " CHARACTER SET 'utf8' "
索引 默认为空
以下是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( // 要创建索引的数据库字段名
            0 => 'prefix',
        ),
        'prefix' => '' // 索引的类型 UNIQUE|FULLTEXT|SPATIAL 如果为空 为一般的索引
        'type' => '' // 指定索引算法 BTREE | HASH | RTREE
    )
)
?>
版本号
<?php
'version' => '$Rev: 44008 $'
?>
是否备份 true:不备份, false:备份(默认)
<?php
'unbackup' => true
?>
是否缓存 true:不缓存, false:缓存(默认)
<?php
'ignore_cache' => true
?>
mysql引擎 如果没有指定 为mysql默认设置
<?php
'engine' => 'innodb'
?>
表描述
<?php
'comment' => app::get('b2c')->_('商品规格索引表')
?>
<?php
'label' => app::get('b2c')->_('分类')
?>

<?php
'width' => "150"
?>
定义desktop列表中本列的初始宽度
<?php
'editable' => true
?>
定义在desktop列表中本列数据数据是否能进行编辑
是否在列表上进行编辑 true:可以 false:不可以(默认)
<?php
'in_list' => true
?>
定义在desktop列表中是否显示 true:是 false:否(默认)
<?php
'default_in_list' => true
?>
默认在desktop列表中是否显示 true:是 false:否(默认)如果有相关列表项配置 按配置显示
<?php
'filterdefault' => true
?>
默认在desktop高级搜索中是否默认显示 true:是 false:否(默认)如果有相关搜索项配置 按配置显示
<?php
'filtertype' => 'normal' // normal按type的来生成过滤  custom 按dbschema中设定的filtercustom 设置过滤
?>
列表页中简单搜索的处理方式,如果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)."') ",
?>
 
该属性的意义为是否为链接显示字段,true(是) false(否),不设置该属性默认为false。注意:该属性为唯一性属性,将多个字段设置为该属性时,会默认显示第一个设置字段。如果被链接的表没有一个字段被设置为,'is_title'=>true,则默认情况会显示该表主键的下一个字段。
数据库抽象层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'=>''//其他扩展语法
);