- app: yxcms
- 参考:
0x01 yxcms model层
此处分析有些长,可跳过…
总结一下yxcms的 数据库操作
- 从文件结构来看, 从model层下
apps下对应着几个模块,每个模块都有完整的mvc。在看model层,么一个model都继承自baseModel
:protected/base/model/baseModel.php
<?php
class 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层:
<?php
class model{
public $model = NULL;
public $db = NULL;
protected $table = "";
protected $ignoreTablePrefix = false;
# 初始化生成db
public 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;