/**
* 获取一个模型
*
* @author Garbin
* @param string $model_name
* @param array $params
* @param book $is_new
* @return object
*/
function &m($model_name, $params = array(), $is_new = false)
{
static $models = array();
$model_hash = md5($model_name . var_export($params, true));
if ($is_new || !isset($models[$model_hash]))
{
$model_file = ROOT_PATH . '/includes/models/' . $model_name . '.model.php';
if (!is_file($model_file))
{
/* 不存在该文件,则无法获取模型 */
return false;
}
include_once($model_file);
$model_name = ucfirst($model_name) . 'Model';
if ($is_new)
{
return new $model_name($params, db());
}
$models[$model_hash] = new $model_name($params, db());
}

return $models[$model_hash];
}

/**
* 获取一个业务模型
*
* @param string $model_name
* @param array $params
* @param bool $is_new
* @return object
*/
function &bm($model_name, $params = array(), $is_new = false)
{
static $models = array();
$model_hash = md5($model_name . var_export($params, true));
if ($is_new || !isset($models[$model_hash]))
{
$model_file = ROOT_PATH . '/includes/models/' . $model_name . '.model.php';
if (!is_file($model_file))
{
/* 不存在该文件,则无法获取模型 */
return false;
}
include_once($model_file);
$model_name = ucfirst($model_name) . 'BModel';
if ($is_new)
{
return new $model_name($params, db());
}
$models[$model_hash] = new $model_name($params, db());
}

return $models[$model_hash];
}


所谓模型,则是一个一个的数据实体,换句话说就是一个数据表,你可以基于这个模
型,调用model.base.php中的数据库操作函数来 对数据进行增、删、改、查的操作。

这里的业务模型,是在实体模型基础上,再继承一次,然后对一些方法进行重写。
系统中只有三个实体有业务模型:
推荐类型 recommend;商品数据模型 goods;商品分类业务模型 gcategory;

具体操作例子:


​​1​​
​​//物品表的操作:​​


​​2​​
​​$model_goods​​​ ​​= & m(​​​​'goods'​​​​);​​


​​3​​
​​$goods_info​​​ ​​= ​​​​$model_goods​​​​->get(​​​​$goods_id​​​​);​​

这里需要解释一下对于数据模型的操作是怎样的一个函数调用过程:
首先:$model_goods = &m(‘goods’);
我 们看一下&m()函数的代码,其中var_export()函数则是将传进来的实体,返回相应的实体类对象,因为所有的model都继承至 model.base.php中的BaseModel类,这个类中定义了基本所有的操作函数,因此$model_goods对象可以对数据库进行相应的操 作。
而我们再看看goods.model.php中的GoodsModel的代码:
​​1​​
​​class​​​ ​​GoodsModel ​​​​extends​​​ ​​BaseModel​​


​​2​​
​​{​​


​​3​​
​​var​​​ ​​$table​​​ ​​= ​​​​'goods'​​​​;​​


​​4​​
​​var​​​ ​​$prikey​​​ ​​= ​​​​'goods_id'​​​​;​​


​​5​​
​​var​​​ ​​$alias​​​ ​​= ​​​​'g'​​​​;​​​​//缩写​​


​​6​​
​​var​​​ ​​$_name​​​ ​​= ​​​​'goods'​​​​;​​


​​7​​
​​var​​​ ​​$temp​​​​; ​​​​// 临时变量​​


​​8​​
​​var​​​ ​​$_relation​​​ ​​= ​​​​array​​​​(​​


​​9​​
​​// 一个商品对应一条商品统计记录​​


​​10​​
​​'has_goodsstatistics'​​​ ​​=> ​​​​array​​​​(​​


​​11​​
​​'model'​​​ ​​=> ​​​​'goodsstatistics'​​​​,​​


​​12​​
​​'type'​​​ ​​=> HAS_ONE,​​


​​13​​
​​'foreign_key'​​​ ​​=> ​​​​'goods_id'​​​​,​​


​​14​​
​​'dependent'​​​ ​​=> true​​


​​15​​
​​),​​


​​16​​
​​// 一个商品对应多个规格​​


​​17​​
​​'has_goodsspec'​​​ ​​=> ​​​​array​​​​(​​


​​18​​
​​'model'​​​ ​​=> ​​​​'goodsspec'​​​​,​​


​​19​​
​​'type'​​​ ​​=> HAS_MANY,​​


​​20​​
​​'foreign_key'​​​ ​​=> ​​​​'goods_id'​​​​,​​


​​21​​
​​'dependent'​​​ ​​=> true​​


​​22​​
​​),​​


​​23​​
​​// 一个商品对应一个默认规格​​


​​24​​
​​'has_default_spec'​​​ ​​=> ​​​​array​​​​(​​


​​25​​
​​'model'​​​ ​​=> ​​​​'goodsspec'​​​​,​​


​​26​​
​​'type'​​​ ​​=> HAS_ONE,​​


​​27​​
​​'refer_key'​​​ ​​=> ​​​​'default_spec'​​​​,​​


​​28​​
​​'foreign_key'​​​ ​​=> ​​​​'spec_id'​​​​,​​


​​29​​
​​),​​


​​30​​
​​// 一个商品对应多个属性​​


​​31​​
​​'has_goodsattr'​​​ ​​=> ​​​​array​​​​(​​


​​32​​
​​'model'​​​ ​​=> ​​​​'goodsattr'​​​​,​​


​​33​​
​​'type'​​​ ​​=> HAS_MANY,​​


​​34​​
​​'foreign_key'​​​ ​​=> ​​​​'goods_id'​​​​,​​


​​35​​
​​'dependent'​​​ ​​=> true​​


​​36​​
​​),​​


​​37​​
​​// 一个商品对应多个图片​​


​​38​​
​​'has_goodsimage'​​​ ​​=> ​​​​array​​​​(​​


​​39​​
​​'model'​​​ ​​=> ​​​​'goodsimage'​​​​,​​


​​40​​
​​'type'​​​ ​​=> HAS_MANY,​​


​​41​​
​​'foreign_key'​​​ ​​=> ​​​​'goods_id'​​​​,​​


​​42​​
​​'dependent'​​​ ​​=> true​​


​​43​​
​​),​​


​​44​​
​​// 一个商品只能属于一个店铺​​


​​45​​
​​'belongs_to_store'​​​ ​​=> ​​​​array​​​​(​​


​​46​​
​​'model'​​​ ​​=> ​​​​'store'​​​​,​​


​​47​​
​​'type'​​​ ​​=> BELONGS_TO,​​


​​48​​
​​'foreign_key'​​​ ​​=> ​​​​'store_id'​​​​,​​


​​49​​
​​'reverse'​​​ ​​=> ​​​​'has_goods'​​​​,​​


​​50​​
​​),​​


​​51​​
​​// 商品和分类是多对多的关系​​


​​52​​
​​'belongs_to_gcategory'​​​ ​​=> ​​​​array​​​​(​​


​​53​​
​​'model'​​​ ​​=> ​​​​'gcategory'​​​​,​​


​​54​​
​​'type'​​​ ​​=> HAS_AND_BELONGS_TO_MANY,​​


​​55​​
​​'middle_table'​​​ ​​=> ​​​​'category_goods'​​​​,​​


​​56​​
​​'foreign_key'​​​ ​​=> ​​​​'goods_id'​​​​,​​


​​57​​
​​'reverse'​​​ ​​=> ​​​​'has_goods'​​​​,​​


​​58​​
​​),​​


​​59​​
​​// 商品和会员是多对多的关系(会员收藏商品)​​


​​60​​
​​'be_collect'​​​ ​​=> ​​​​array​​​​(​​


​​61​​
​​'model'​​​ ​​=> ​​​​'member'​​​​,​​


​​62​​
​​'type'​​​ ​​=> HAS_AND_BELONGS_TO_MANY,​​


​​63​​
​​'middle_table'​​​ ​​=> ​​​​'collect'​​​​,​​


​​64​​
​​'foreign_key'​​​ ​​=> ​​​​'item_id'​​​​,​​


​​65​​
​​'ext_limit'​​​ ​​=> ​​​​array​​​​(​​​​'type'​​​ ​​=> ​​​​'goods'​​​​),​​


​​66​​
​​'reverse'​​​ ​​=> ​​​​'collect_goods'​​​​,​​


​​67​​
​​),​​


​​68​​
​​// 商品和推荐类型是多对多的关系 todo​​


​​69​​
​​'be_recommend'​​​ ​​=> ​​​​array​​​​(​​


​​70​​
​​'model'​​​ ​​=> ​​​​'recommend'​​​​,​​


​​71​​
​​'type'​​​ ​​=> HAS_AND_BELONGS_TO_MANY,​​


​​72​​
​​'middle_table'​​​ ​​=> ​​​​'recommended_goods'​​​​,​​


​​73​​
​​'foreign_key'​​​ ​​=> ​​​​'goods_id'​​​​,​​


​​74​​
​​'reverse'​​​ ​​=> ​​​​'recommend_goods'​​​​,​​


​​75​​
​​),​​


​​76​​
​​);​​


​​77​​
​​var​​​ ​​$_autov​​​ ​​= ​​​​array​​​​(​​


​​78​​
​​'goods_name'​​​ ​​=> ​​​​array​​​​(​​


​​79​​
​​'required'​​​ ​​=> true,​​


​​80​​
​​'filter'​​​ ​​=> ​​​​'trim'​​​​,​​


​​81​​
​​),​​


​​82​​
​​);​​


​​83​​
​​}​​

这里贴出了实体goods模型类中的内容,先是表格的属性,再就是goods与其它实体之间的关联关系的定义。然后我们再看看这个函数,它是 BaseModel构造函数里调用的方法,对对象中的基础变量进行初使化:

​​1​​
​​function​​​ ​​BaseModel(​​​​$params​​​​, ​​​​$db​​​​)​​


​​2​​
​​{​​


​​3​​
​​$this​​​​->db =& ​​​​$db​​​​;​​


​​4​​
​​!​​​​$this​​​​->alias && ​​​​$this​​​​->alias = ​​​​$this​​​​->table;​​


​​5​​
​​$this​​​​->_prefix = DB_PREFIX;​​


​​6​​
​​$this​​​​->table = ​​​​$this​​​​->_prefix . ​​​​$this​​​​->table;​​


​​7​​
​​if​​​ ​​(!emptyempty(​​​​$params​​​​))​​


​​8​​
​​{​​


​​9​​
​​foreach​​​ ​​(​​​​$params​​​ ​​as​​​ ​​$key​​​ ​​=> ​​​​$value​​​​)​​


​​10​​
​​{​​


​​11​​
​​$this​​​​->​​​​$key​​​ ​​= ​​​​$value​​​​;​​


​​12​​
​​}​​


​​13​​
​​}​​


​​14​​
​​}​​

大家已经看出$_relation 中间是此实体的关联信息,然后在BaseModel类中的一个函数:

​​1​​
​​function​​​ ​​_getJoinString(​​​​$relation_info​​​​)​​


​​2​​
​​{​​


​​3​​
​​switch​​​ ​​(​​​​$relation_info​​​​[​​​​'type'​​​​])​​


​​4​​
​​{​​


​​5​​
​​case​​​ ​​HAS_ONE:​​​​//​​


​​6​​
​​$model​​​ ​​=& m(​​​​$relation_info​​​​[​​​​'model'​​​​]);​​


​​7​​
​​/* 联合限制 */​​


​​8​​
​​$ext_limit​​​ ​​= ​​​​''​​​​;​​


​​9​​
​​$relation_info​​​​[​​​​'ext_limit'​​​​] && ​​​​$ext_limit​​​ ​​= ​​​​' AND '​​​ ​​. ​​​​$this​​​​->_getExtLimit(​​​​$relation_info​​​​[​​​​'ext_limit'​​​​]);​​


​​10​​
​​/* 获取参考键,默认是本表主键(直接拥有),否则为间接拥有 */​​


​​11​​
​​$refer_key​​​ ​​= isset(​​​​$relation_info​​​​[​​​​'refer_key'​​​​]) ?​​​​$relation_info​​​​[​​​​'refer_key'​​​​] : ​​​​$this​​​​->prikey;​​


​​12​​
​​/* 本表参考键=外表外键 */​​


​​13​​
​​return​​​ ​​" LEFT JOIN {$model->table} {$model->alias} ON {$this->alias}.{$refer_key}={$model->alias}.{$relation_info['foreign_key']}{$ext_limit}"​​​​;​​


​​14​​
​​break​​​​;​​


​​15​​
​​case​​​ ​​BELONGS_TO:​​


​​16​​
​​/* 属于关系与拥有是一个反向的关系 */​​


​​17​​
​​$model​​​ ​​=& m(​​​​$relation_info​​​​[​​​​'model'​​​​]);​​


​​18​​
​​$be_related​​​ ​​= ​​​​$model​​​​->getRelation(​​​​$relation_info​​​​[​​​​'reverse'​​​​]);​​


​​19​​
​​if​​​ ​​(emptyempty(​​​​$be_related​​​​))​​


​​20​​
​​{​​


​​21​​
​​/* 没有找到反向关系 */​​


​​22​​
​​$this​​​​->_error(​​​​'no_reverse_be_found'​​​​,​​​​$relation_info​​​​[​​​​'model'​​​​]);​​


​​23​​
​​return​​​ ​​''​​​​;​​


​​24​​
​​}​​


​​25​​
​​$ext_limit​​​ ​​= ​​​​''​​​​;​​


​​26​​
​​!emptyempty(​​​​$relation_info​​​​[​​​​'ext_limit'​​​​]) && ​​​​$ext_limit​​​ ​​= ​​​​' AND '​​​ ​​. ​​​​$this​​​​->_getExtLimit(​​​​$relation_info​​​​[​​​​'ext_limit'​​​​], ​​​​$this​​​​->alias);​​


​​27​​
​​/* 获取参考键,默认是外表主键 */​​


​​28​​
​​$refer_key​​​ ​​= isset(​​​​$be_related​​​​[​​​​'refer_key'​​​​]) ?​​​​$be_related​​​​[​​​​'refer_key'​​​​] :​​​​$model​​​​->prikey ;​​


​​29​​
​​/* 本表外键=外表参考键 */​​


​​30​​
​​return​​​ ​​" LEFT JOIN {$model->table} {$model->alias} ON {$this->alias}.{$be_related['foreign_key']} = {$model->alias}.{$refer_key}{$ext_limit}"​​​​;​​


​​31​​
​​break​​​​;​​


​​32​​
​​case​​​ ​​HAS_AND_BELONGS_TO_MANY:​​


​​33​​
​​/* 连接中间表,本表主键=中间表外键 */​​


​​34​​
​​$malias​​​ ​​= isset(​​​​$relation_info​​​​[​​​​'alias'​​​​]) ?​​​​$relation_info​​​​[​​​​'alias'​​​​] : ​​​​$relation_info​​​​[​​​​'middle_table'​​​​];​​


​​35​​
​​$ext_limit​​​ ​​= ​​​​''​​​​;​​


​​36​​
​​$relation_info​​​​[​​​​'ext_limit'​​​​] && ​​​​$ext_limit​​​ ​​= ​​​​' AND '​​​ ​​. ​​​​$this​​​​->_getExtLimit(​​​​$relation_info​​​​[​​​​'ext_limit'​​​​], ​​​​$malias​​​​);​​


​​37​​
​​return​​​ ​​" LEFT JOIN {$this->_prefix}{$relation_info['middle_table']} {$malias} ON {$this->alias}.{$this->prikey} = {$malias}.{$relation_info['foreign_key']}{$ext_limit}"​​​​;​​


​​38​​
​​break​​​​;​​


​​39​​
​​}​​


​​40​​
​​}​​


​​41​​
​​/* 模型相关常量定义 */​​


​​42​​
​​define(​​​​'HAS_ONE'​​​​, 1); ​​​​//一对一关联​​


​​43​​
​​define(​​​​'BELONGS_TO'​​​​, 2); ​​​​//属于关联​​


​​44​​
​​define(​​​​'HAS_MANY'​​​​, 3); ​​​​//一对多关联​​


​​45​​
​​define(​​​​'HAS_AND_BELONGS_TO_MANY'​​​​, 4); ​​​​//多对多关联​​


​​46​​
​​define(​​​​'DROP_CONDITION_TRUNCATE'​​​​, ​​​​'TRUNCATE'​​​​); ​​​​// 清空​​

从这个函数中,我们可以看到,对于不同的关联关系,它会返回不同的关联时的查询语句片断,然后连接上主sql语句,就可以针对实体的关联实体进行相 应的关联操作了。

​​1​​
​​//物品表的操作:​​


​​2​​
​​$model_goods​​​ ​​= & m(​​​​'goods'​​​​);​​


​​3​​
​​$goods_info​​​ ​​= ​​​​$model_goods​​​​->find(​​​​array​​​​(​​


​​4​​
​​'conditions'​​​ ​​=> ​​​​"if_show=1 and closed=0"​​​​,​​


​​5​​
​​'fields'​​​ ​​=> ​​​​'goods_id,goods_name,s.store_id,s.store_name'​​​​,​​


​​6​​
​​'join'​​​ ​​=> ​​​​'blongs_to_store'​​


​​7​​
​​));​​

这里的’join’ => ‘blongs_to_store’ ,我们从上面的:

Php代码

​​1​​
​​// 一个商品只能属于一个店铺​​


​​2​​
​​'belongs_to_store'​​​ ​​=> ​​​​array​​​​(​​


​​3​​
​​'model'​​​ ​​=> ​​​​'store'​​​​,​​


​​4​​
​​'type'​​​ ​​=> BELONGS_TO,​​


​​5​​
​​'foreign_key'​​​ ​​=> ​​​​'store_id'​​​​,​​


​​6​​
​​'reverse'​​​ ​​=> ​​​​'has_goods'​​​​,​​


​​7​​
​​),​​

这里我们可以知道这是在与store表进行关联查找了。
到这里,读者就可以知道,如果在上面进行二次开发的话,怎样进行数据库操作就已经很 明确的了。
在BaseModel与cls_mysql(mysql.php)中,有很多的有关数据操作的函数,这里就不需要再一一进行解释了,而 在cls_mysql中,有一些更基础的操作函数,还有仿真 Adodb 的函数,可以直接跳过BaseModel中的函数
以上介绍了如何在 ecmall的平台上进行数据库操作,如果操作更加的复杂,这里还有一种更加直接的方法: Php代码

​​1​​
​​$sql​​​ ​​= ​​​​"select g.goods_id,g.goods_name, from "​​​​.DB_PREFIX.​​​​"goods g, "​​​​.DB_PREFIX.​​​​"goods_spec gs , "​​​​.DB_PREFIX.​​​​"store s where cate_id='"​​​​.​​​​$cate_id​​​​.​​​​"' AND g.if_show = 1 AND g.closed = 0 and g.goods_id=gs.goods_id and g.store_id=s.store_id and gs.stock>0 and s.state=1 order by g.add_time desc limit 6"​​​​;​​


​​2​​
​​$goods_mod​​​ ​​=& m(​​​​'goods'​​​​);​​


​​3​​
​​$category_goods​​​ ​​= ​​​​$goods_mod​​​​->getAll(​​​​$sql​​​​);​​


​​4​​
​​if​​​​(!​​​​$category_goods​​​​){​​


​​5​​
​​$category_goods​​​​=​​​​array​​​​();​​


​​6​​
​​}​​


​​7​​
​​return​​​ ​​$category_goods​​​​;​​

就可以直接使用sql语句进行数据操作了。
还可以在BaseModel中定义自己的操作方法,其中可以使用$this->db->(cls_mysql中定义的方法) 来调用cls_mysql中的函数,从而可以添加更加复杂的数据操作函数。