<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id: Model.class.php 2815 2012-03-13 07:08:56Z liu21st $
/**
+------------------------------------------------------------------------------
* ThinkPHP Model模型类
* 实现了ORM和ActiveRecords模式
+------------------------------------------------------------------------------
* @category Think
* @package Think
* @subpackage Core
* @author liu21st <liu21st@gmail.com>
* @version $Id: Model.class.php 2815 2012-03-13 07:08:56Z liu21st $
+------------------------------------------------------------------------------
*/
class Model {
// 操作状态
const MODEL_INSERT = 1; // 插入模型数据
const MODEL_UPDATE = 2; // 更新模型数据
const MODEL_BOTH = 3; // 包含上面两种方式
const MUST_VALIDATE = 1;// 必须验证
const EXISTS_VAILIDATE = 0;// 表单存在字段则验证
const VALUE_VAILIDATE = 2;// 表单值不为空则验证
// 当前使用的扩展模型
private $_extModel = null;
// 当前数据库操作对象
protected $db = null;
// 主键名称
protected $pk = 'id';
// 数据表前缀
protected $tablePrefix = '';
// 模型名称
protected $name = '';
// 数据库名称
protected $dbName = '';
// 数据表名(不包含表前缀)
protected $tableName = '';
// 实际数据表名(包含表前缀)
protected $trueTableName ='';
// 最近错误信息
protected $error = '';
// 字段信息
protected $fields = array();
// 数据信息
protected $data = array();
// 查询表达式参数
protected $options = array();
protected $_validate = array(); // 自动验证定义
protected $_auto = array(); // 自动完成定义
protected $_map = array(); // 字段映射定义
// 是否自动检测数据表字段信息
protected $autoCheckFields = true;
// 是否批处理验证
protected $patchValidate = false;
/**
+----------------------------------------------------------
* 架构函数
* 取得DB类的实例对象 字段检查
+----------------------------------------------------------
* @param string $name 模型名称
* @param string $tablePrefix 表前缀
* @param mixed $connection 数据库连接信息
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
*/
public function __construct($name='',$tablePrefix='',$connection='') {
// 模型初始化
$this->_initialize();
// 获取模型名称
if(!empty($name)) {
if(strpos($name,'.')) { // 支持 数据库名.模型名的 定义
list($this->dbName,$this->name) = explode('.',$name);
}else{
$this->name = $name;
}
}elseif(empty($this->name)){
$this->name = $this->getModelName();
}
// 设置表前缀
if(is_null($tablePrefix)) {// 前缀为Null表示没有前缀
$this->tablePrefix = '';
}elseif('' != $tablePrefix) {
$this->tablePrefix = $tablePrefix;
}else{
$this->tablePrefix = $this->tablePrefix?$this->tablePrefix:C('DB_PREFIX');
}
// 数据库初始化操作
// 获取数据库操作对象
// 当前模型有独立的数据库连接信息
$this->db(0,empty($this->connection)?$connection:$this->connection);
}
/**
+----------------------------------------------------------
* 自动检测数据表信息
+----------------------------------------------------------
* @access protected
+----------------------------------------------------------
* @return void
+----------------------------------------------------------
*/
protected function _checkTableInfo() {
// 如果不是Model类 自动记录数据表信息
// 只在第一次执行记录
if(empty($this->fields)) {
// 如果数据表字段没有定义则自动获取
if(C('DB_FIELDS_CACHE')) {
$db = $this->dbName?$this->dbName:C('DB_NAME');
$this->fields = F('_fields/'.$db.'.'.$this->name);
if(!$this->fields) $this->flush();
}else{
// 每次都会读取数据表信息
$this->flush();
}
}
}
/**
+----------------------------------------------------------
* 获取字段信息并缓存
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @return void
+----------------------------------------------------------
*/
public function flush() {
// 缓存不存在则查询数据表信息
$this->db->setModel($this->name);
$fields = $this->db->getFields($this->getTableName());
if(!$fields) { // 无法获取字段信息
return false;
}
$this->fields = array_keys($fields);
$this->fields['_autoinc'] = false;
foreach ($fields as $key=>$val){
// 记录字段类型
$type[$key] = $val['type'];
if($val['primary']) {
$this->fields['_pk'] = $key;
if($val['autoinc']) $this->fields['_autoinc'] = true;
}
}
// 记录字段类型信息
if(C('DB_FIELDTYPE_CHECK')) $this->fields['_type'] = $type;
// 2008-3-7 增加缓存开关控制
if(C('DB_FIELDS_CACHE')){
// 永久缓存数据表信息
$db = $this->dbName?$this->dbName:C('DB_NAME');
F('_fields/'.$db.'.'.$this->name,$this->fields);
}
}
/**
+----------------------------------------------------------
* 动态切换扩展模型
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $type 模型类型名称
* @param mixed $vars 要传入扩展模型的属性变量
+----------------------------------------------------------
* @return Model
+----------------------------------------------------------
*/
public function switchModel($type,$vars=array()) {
$class = ucwords(strtolower($type)).'Model';
if(!class_exists($class))
throw_exception($class.L('_MODEL_NOT_EXIST_'));
// 实例化扩展模型
$this->_extModel = new $class($this->name);
if(!empty($vars)) {
// 传入当前模型的属性到扩展模型
foreach ($vars as $var)
$this->_extModel->setProperty($var,$this->$var);
}
return $this->_extModel;
}
/**
+----------------------------------------------------------
* 设置数据对象的值
+----------------------------------------------------------
* @access public
+---------------