ecmall 模型分析

/**
 *  获取一个模型
 *
 *  @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中的函数,从而可以添加更加复杂的数据操作函数。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值