以下文档均以最新的shopex 4.8.5 为准。
程序为mvc 3层结构:模型-视图-控制器。
模型是前后台公用。完成业务逻辑,所有的数据库操作,文件等资源调用,都由此层实现。
控制器则是前后台独立。负责业务模型的调用,拼接,变量的转换等等。
视图层采用类似smarty的实现。
在任何时候都有一个全局变量$system指向唯一的一个内核类:core/kernel.php
公共类图
结构图
公共函数库位于/core/func_ext.php,它在内核加载时首先被加载,对全系统有效。其中包含若干php5函数的php4模拟版本:
file_put_contents
json_encode
json_decode
ftp_chmod
array_diff_key
http_build_query
控制器负责所有的变量的转换,包括对外界的变量转换。像胶水一样粘合各个业务model,并在其中的数据交互过程中做一些数据转换过程。最终将变量抛到模板层。 模板层负责编译成html输出,这里我们创建了大量的smarty插件来减少开发者的重复工作量。
model层负责所有的资源操作,包括数据库和文件系统以及读取网络等等。
业务模型层下面是schema,这些是对数据库表结构的最底层的描述。
我们将从底向上的介绍这些层次
1. 数据库结构定义文件
在485之前,我们使用powerdesigner来管理这些表结构,但是在一些项目的版本管理过程中,有时需要维护多个版本。powerdesigner的储存文件为一个单一的巨大的xml格式pdm文件。 这在进行版本的合并分支时几乎无法处理。
而在485里,我们使用php去描述表结构有了以下几个优势:
数据库定义具有版本管理特性
各分支开发互不干扰
协同更改时,可以进行合并操作
针对单表的版本还原与操作日志
容易做自动化的表结构对比
更快速的getInsertSQL/getUpdateSQL: 不需要select * from xxx where 0=1
插件可以有自己的表定义文件
为model::getColumns自动化做准备
按照用途来定义字段类型,不会出现同一种数据类型而字段定义不一致的情况
简单的外键实现,方便的统计表的依赖关系,使得外键字段定义完全一致
更好的mysql版本兼容:type = MyISAM DEFAULT CHARACTER SET语法
很方便的实现gbk/utf8多版本
现在这些数据库定义文件放置在 core/schemas 下面,每个表一个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'=>''//其他扩展语法
);
好了,现在一切的表结构都可以被系统精确控制了。 利用这个东西,我们实现了485里的数据表结构比较功能,并且以这个为基础建立了新的升级机制。 并且在未来,这将是app体系的一个基石,
关于app体系,我将在后来的章节讲解,这将是一个神奇的东西。
2. 网店对象
在model里面,有一些特别特别的类是基于shopObject这个类的。 shopObject用来表示一些有共性和意义的对象,比如商品,订单,会员。 有一些抽象的共用方法。
每个shopObject都有一个绑定的表,并且标明了哪些字段是主键。因此我们可以做一些批量的东西。 后台的订单列表,商品列表,会员列表等等。我们给他取名为finder。在此向osx致以敬意。
is_highlight($row) <--->行数据<---> bool <--->用来判断是否将该行高亮
因此如果你想修改这些默认行为,比如在列上加些自定义的字段,而这个字段可能完全不是数据库里,而存在于其他某外部系统中。 那么很简单,你只需要重载对应的方法即可。
你可以去思考将这个重载放在哪一层。如果希望所有调用这个数据的地方都变化,那么就重载model。
如果只是希望后台的列表增加一个列,就重载他的控制器即可
shopObject还有一个特性,就是支持事件广播。 他有一个特殊的方法:shopObject::fireEvent($eventName) 用来广播事件。 其他对象采用观察者模式listen到感兴趣的对象上。
当订单新建时,系统会调用相应的$orderModel->firevent('create')方法, 这时所有关注order-create的函数就全都被纷纷调用,有的负责发邮件通知用户,有的负责记录的数据库,有的可能是插件写的:将这些事件广播道某esb系统里。
这时一条网店系统的数字神经,当订单新建,或者会员登录的时候。我们可以通过外挂的脚本做一些触发事件。 这也是485网店机器人的基础。
3. 业务模型(model)
模型是前后台公用。完成业务逻辑,所有的数据库操作,文件等资源调用,都由此层实现。
模块调用方法: $systme->loadModel(path/to/a/model); 载入过程如图所示:
1
评论列表()