`
anysky131
  • 浏览: 172062 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

有关ecmall的东东2----数据库关系模型的实现

    博客分类:
  • PHP
阅读更多

对于数据库关系模型的分析,我觉得需要从两个函数说起:

//获取一个模型
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];
}

//获取一个业务模型
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;

具体操作例子:

//物品表的操作:
$model_goods = & m('goods');
$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的代码:

class GoodsModel extends BaseModel
{
    var $table  = 'goods';
    var $prikey = 'goods_id';
    var $alias  = 'g';//缩写
    var $_name  = 'goods';
    var $temp; // 临时变量
    var $_relation = array(
        // 一个商品对应一条商品统计记录
        'has_goodsstatistics' => array(
            'model'         => 'goodsstatistics',
            'type'          => HAS_ONE,
            'foreign_key'   => 'goods_id',
            'dependent'     => true
        ),
        // 一个商品对应多个规格
        'has_goodsspec' => array(
            'model'         => 'goodsspec',
            'type'          => HAS_MANY,
            'foreign_key'   => 'goods_id',
            'dependent'     => true
        ),
        // 一个商品对应一个默认规格
        'has_default_spec' => array(
            'model'         => 'goodsspec',
            'type'          => HAS_ONE,
            'refer_key'     => 'default_spec',
            'foreign_key'   => 'spec_id',
        ),
        // 一个商品对应多个属性
        'has_goodsattr' => array(
            'model'         => 'goodsattr',
            'type'          => HAS_MANY,
            'foreign_key'   => 'goods_id',
            'dependent'     => true
        ),
        // 一个商品对应多个图片
        'has_goodsimage' => array(
            'model'         => 'goodsimage',
            'type'          => HAS_MANY,
            'foreign_key'   => 'goods_id',
            'dependent'     => true
        ),
        // 一个商品只能属于一个店铺
        'belongs_to_store' => array(
            'model'         => 'store',
            'type'          => BELONGS_TO,
            'foreign_key'   => 'store_id',
            'reverse'       => 'has_goods',
        ),
        // 商品和分类是多对多的关系
        'belongs_to_gcategory' => array(
            'model'         => 'gcategory',
            'type'          => HAS_AND_BELONGS_TO_MANY,
            'middle_table'  => 'category_goods',
            'foreign_key'   => 'goods_id',
            'reverse'       => 'has_goods',
        ),
        // 商品和会员是多对多的关系(会员收藏商品)
        'be_collect' => array(
            'model'         => 'member',
            'type'          => HAS_AND_BELONGS_TO_MANY,
            'middle_table'  => 'collect',
            'foreign_key'   => 'item_id',
            'ext_limit'     => array('type' => 'goods'),
            'reverse'       => 'collect_goods',
        ),
        // 商品和推荐类型是多对多的关系 todo
        'be_recommend' => array(
            'model'         => 'recommend',
            'type'          => HAS_AND_BELONGS_TO_MANY,
            'middle_table'  => 'recommended_goods',
            'foreign_key'   => 'goods_id',
            'reverse'       => 'recommend_goods',
        ),
    );

    var $_autov = array(
        'goods_name' => array(
            'required'  => true,
            'filter'    => 'trim',
        ),
    );

}

 

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

function BaseModel($params, $db)
    {
        $this->db =& $db;
        !$this->alias && $this->alias = $this->table;
        $this->_prefix = DB_PREFIX;
        $this->table = $this->_prefix . $this->table;
        if (!empty($params))
        {
            foreach ($params as $key => $value)
            {
                $this->$key = $value;
            }
        }
    }

 

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

 function _getJoinString($relation_info)
    {
        switch ($relation_info['type'])
        {
            case HAS_ONE://
                $model =& m($relation_info['model']);

                /* 联合限制 */
                $ext_limit = '';
                $relation_info['ext_limit'] && $ext_limit = ' AND ' . $this->_getExtLimit($relation_info['ext_limit']);

                /* 获取参考键,默认是本表主键(直接拥有),否则为间接拥有 */
                $refer_key = isset($relation_info['refer_key']) ? $relation_info['refer_key'] : $this->prikey;

                /* 本表参考键=外表外键 */
                return " LEFT JOIN {$model->table} {$model->alias} ON {$this->alias}.{$refer_key}={$model->alias}.{$relation_info['foreign_key']}{$ext_limit}";
            break;
            case BELONGS_TO:
                /* 属于关系与拥有是一个反向的关系 */
                $model =& m($relation_info['model']);
                $be_related = $model->getRelation($relation_info['reverse']);
                if (empty($be_related))
                {
                    /* 没有找到反向关系 */
                    $this->_error('no_reverse_be_found', $relation_info['model']);

                    return '';
                }
                $ext_limit = '';
                !empty($relation_info['ext_limit']) && $ext_limit = ' AND ' . $this->_getExtLimit($relation_info['ext_limit'], $this->alias);
                /* 获取参考键,默认是外表主键 */
                $refer_key = isset($be_related['refer_key']) ? $be_related['refer_key'] :$model->prikey ;

                /* 本表外键=外表参考键 */
                return " LEFT JOIN {$model->table} {$model->alias} ON {$this->alias}.{$be_related['foreign_key']} = {$model->alias}.{$refer_key}{$ext_limit}";
            break;
            case HAS_AND_BELONGS_TO_MANY:
                /* 连接中间表,本表主键=中间表外键 */
                $malias = isset($relation_info['alias']) ? $relation_info['alias'] : $relation_info['middle_table'];
                $ext_limit = '';
                $relation_info['ext_limit'] && $ext_limit = ' AND ' . $this->_getExtLimit($relation_info['ext_limit'], $malias);
                return " LEFT JOIN {$this->_prefix}{$relation_info['middle_table']} {$malias} ON {$this->alias}.{$this->prikey} = {$malias}.{$relation_info['foreign_key']}{$ext_limit}";
            break;
        }
    }
/* 模型相关常量定义 */
define('HAS_ONE', 1);                     //一对一关联
define('BELONGS_TO', 2);                  //属于关联
define('HAS_MANY', 3);                    //一对多关联
define('HAS_AND_BELONGS_TO_MANY', 4);     //多对多关联
define('DROP_CONDITION_TRUNCATE', 'TRUNCATE');  //清空

 

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

 

具体操作例子:

//物品表的操作:
$model_goods = & m('goods');
$goods_info = $model_goods->find(array(
				'conditions' => "if_show=1 and closed=0",
				'fields'         => 'goods_id,goods_name,s.store_id,s.store_name',
				'join'				=> 'blongs_to_store'
)); 

 

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

// 一个商品只能属于一个店铺
        'belongs_to_store' => array(
            'model'         => 'store',
            'type'          => BELONGS_TO,
            'foreign_key'   => 'store_id',
            'reverse'       => 'has_goods',
        ),

 

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

$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";
		$goods_mod =& m('goods');
            $category_goods = $goods_mod->getAll($sql);
            if(!$category_goods){
            	$category_goods=array();
            }
            return $category_goods;

 

就可以直接使用sql语句进行数据操作了。

还可以在BaseModel中定义自己的操作方法,其中可以使用$this->db->(cls_mysql中定义的方法) 来调用cls_mysql中的函数,从而可以添加更加复杂的数据操作函数。
好了,数据操作分析就这些了,有不对之处,还请拍砖!

分享到:
评论

相关推荐

    ECmall源码简略分析

    ECmall源码简略分析----数据库关系模型的实现

    ECMall 繁体UFT-8 v2.3.0 正式版

     ECMall 2.3.0 正式版更新日志:程序包说明:upload 主程序integrate 整合程序initdata 测试数据安装程序upgrade 升级程序doc 相关文档1、新增 4套店铺风格2、优化 卖家可设置是否启用团购功能3、新增 商品雷达4、...

    ecmall230-0918-scgbk 官方版

    ecmall230-0918-scgbk 官方版,如今官方已经停止ecmall程序下载,据了解,以后也不会开发免费下载了。

    ecmall230-0918-scgbk.zip

    ecmall230-0918-scgbk.zip

    ecmall230-0918-scutf8 代码

    ecmall230-0918-scutf8 代码

    ECMall 2.3.0 繁体utf-8.zip

    ECMall是一个根据融合了电子商务以及网络社区特色的产品,它不仅能使您的电子商务进程变得异常轻松,同时通过和康盛创想相关产品的结合还能进一步提高用户的活跃度以及黏性,从而促进用户的忠诚度。 ECMall 2.3.0...

    ecmall数据库字段

    ecmall数据库字段

    ecmall数据库,数据字典

    ecmall数据库详细的数据字典,描述了各个表以及表中的字段描述

    ecmall数据库字段表

    ecmall 最新所有数据表 字段说明 比较详细 方便二次开发

    ECMall模板-flymak

    ECMall模板 flymak模版,解压后直接放在服务器上打开

    ecmall模板-qqmall

    ecmall模板 qqmall 拍拍模板

    ecmall兼容PHP5.3-PHP7.0

    ecmall电子商城源代码兼容PHP5.3-PHP7.0,由于ecmall开源代码官网已经不更新升级了,PHP5.5以上就会报错,现在做了一个兼容源代码的调整,测试了PHP5.3.29,PHP5.6.27,PHP7.0.12这三个版本可以兼容,下载资源里面附加文档...

    Ecmall 2.X 架构分析与技术指南

    本教程以Ecmall2.X为基准编写的,目的为提高公司研发技术部门的技术知识覆盖,让Ecmall新手快速上手,教材中围绕着MVC模式展开,主要论述了模型的多对多,多对一等关系,更加深层的展示了Ecmall不同层面的底层函数,...

    ECMall v2.3.0 简体UTF-8 正式版

    ECMall v2.3.0 简体UTF-8 正式版 官方需要密码,为新手提供方便。

    ecmall数据库表详解(整理)

    ecmall数据库表结构说明,是在日常工作中整理的网络资源,可能不是很完整,仅供参考,在此分享出来,希望给大家带来一些帮助!

    ecmall2

    ecmall2

    ECMALL数据库分析.pdf

    ECMALL数据库分析.pdf

    ECMALL数据库分析

    ECMALL数据库分析 ECMALL数据库各表分析

    Ecmall 2.X 二次开发设计分析实务

    本文档主要论述了模型的多对多,多对一等关系,更加深层的展示了Ecmall不同层面的底层函数,涉及到更多底层函数应用,本教程原属苏州东创科技园信息研发部所有。因本人时间关系紧张,教材中知识内容难免有不当之处,...

    ecmall-utf8

    ECMall是一个根据融合了电子商务以及网络社区特色的产品,它不仅能使您的电子商务进程变得异常轻松,同时通过和康盛创想相关产品的结合还能进一步提高用户的活跃度以及黏性,从而促进用户的忠诚度。

Global site tag (gtag.js) - Google Analytics