- app: yxcms
- 参考:
0x01 yxcms model层
此处分析有些长,可跳过…
总结一下yxcms的 数据库操作
- 从文件结构来看, 从model层下

apps下对应着几个模块,每个模块都有完整的mvc。在看model层,么一个model都继承自baseModel:protected/base/model/baseModel.php
<?phpclass baseModel extends model{protected $prefix='';public function __construct( $database= 'DB',$force = false ){parent::__construct();$this->prefix=config('DB_PREFIX');}}
baseModel 只有一个构造函数, 他构造了上层model方法,model里构造了基本方法。
控制层对于model层的操作语法是这样的
<?php$var = model('Table')->method($Parameters)# 如:$count = model('photo')
model层的入口在core中:protected/base/model/model
<?php# $model 就是我们传进来的表名嘛function model($model){static $objArray = array();$className = $model . 'Model';if(!is_object($objArray[$className])){if(!class_exists($className)){throw new Exception(config('_APP_NAME'). '/' . $className . '.php 模型类不存在');}这里new了$objArray[$className] = new $className();}return $objArray[$className];}
再看model层:
<?phpclass model{public $model = NULL;public $db = NULL;protected $table = "";protected $ignoreTablePrefix = false;# 初始化生成dbpublic function __construct( $database= 'DB', $force = false){$this->model = self::connect( config($database), $force);$this->db = $this->model->db;}连接函数static public function connect($config, $force=false){static $model = NULL;if( $force==true || empty($model) ){$model = new cpModel($config);}return $model;}public function query($sql){return $this->model->query($sql);}public function find($condition = '', $field = '', $order = ''){return $this->model->table($this->table, $this->ignoreTablePrefix)->field($field)->where($condition)->order($order)->find();}public function select($condition = '', $field = '', $order = '', $limit = ''){return $this->model->table($this->table, $this->ignoreTablePrefix)->field($field)->where($condition)->order($order)->limit($limit)->select();}public function count($condition = ''){return $this->model->table($this->table, $this->ignoreTablePrefix)->where($condition)->count();}public function insert($data = array() ){return $this->model->table($this->table, $this->ignoreTablePrefix)->data($data)->insert();}public function update($condition, $data = array() ){$a = $this->model->table($this->table, $this->ignoreTablePrefix)->data($data)->where($condition)->update();return $this->model->table($this->table, $this->ignoreTablePrefix)->data($data)->where($condition)->update();}public function delete($condition){return $this->model->table($this->table, $this->ignoreTablePrefix)->where($condition)->delete();}public function getSql(){return $this->model->getSql();}public function escape($value){return $this->model->escape($value);}public function cache($time = 0){$this->model->cache($time);return $this;}}
- 首先从
config里连接数据库调用了core里的cpModel,加载了driver。
<?php//连接数据库public function connect() {# 读配置里的数据库驱动$dbDriver = 'cp' . ucfirst( $this->config['DB_TYPE'] );# 加载驱动require_once( dirname(__FILE__) . '/db/' . $dbDriver . '.class.php' );//实例化数据库驱动类$this->db = new $dbDriver( $this->config );}

数据库的读写操作最后还是落到这里面的文件与数据库做对应的api连接, 这里默认配置是第一个cpMysql.class.php。那么如何进入操作的呢?
数据库操作:1. 建立连接 2. 操作 3.释放 在项目中为了做到低耦合模块化总是跳去,但是这些功能都有具体的落实点。比如数据库操作,理清源头,找到哪儿调用了mysql_connect():
连接基本操作在这儿了。
这个方法被_getReadLink或者_getWriteLink形成两个数据库操作句柄$this->_readLink和$this->_writeLink。分成读操作和写操作:
读操作:
写操作:
瞥到了一个escape被循环调用emmm….在这个方法里我们又看到了这玩意….
思想数组递归,不是数组直接过滤,这里array_map实现递归我觉得比较巧妙。
所以yxcms的model层在底层是用了过滤。
在回头看一个完整的查询,控制层的:$cobiunt=model('news')->count($where); 这个是来自default模块,index控制器下的一个查询功能,条件查询,返回news表查询行数。
$where=”ispass=’1’ AND (title like ‘%”.$keywords.”%’ OR description like ‘%”.$keywords.”%’)”;$keyword可控。
两个参数,model(‘news’)初始化了model层的news模块(和通过url访问controller很像)。根据上面的分析,所有的model模块都继承了baseModel<-model,model中抽象了基本操作。所以这条语句中的->count($where)相当于走到了这里。
这里base/model/model.php:
<?public function count($condition = ''){return $this->model->table($this->table, $this->ignoreTablePrefix)->where($condition)->count();}
这还是一个抽象层,做为接口,连接core里的cpmodel,这一层在核心,形成查询表达式,并翻译给指定的driver的做查询。
我们的$where化身成了$condition传到了where中。这是一串多层调用,现调用 table() ,这个方法就是检查表名有没有前缀,然后赋值给了一个参数,还是返回$this始构建查询表达式。这里面的$this->db就开始调用底层驱动cpMysql里的方法了。
where在哪呢?这里做了一些连贯操作。https://www.aspyc.com/archives/604.html使用了_call方法,当没有发现where就运行call:
include/core/cpModel.class.php
<?php//回调方法,连贯操作的实现public function __call($method, $args) {$method = strtolower($method);if ( in_array($method, array('field','data','where','group','having','order','limit','cache')) ) {$this->options[$method] = $args[0]; //接收数据if( $this->options['field'] =='' ) $this->options['field'] = '*';return $this; //返回对象,连贯查询} else{throw new Exception($method . '方法在cpModel.class.php类中没有定义');}}
这里我目前也不是很熟,跳过orm去,打印sql查询语句。
真正的sql语句是$this->db->sql;
