<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id$
define('HAS_ONE',1);
define('BELONGS_TO',2);
define('HAS_MANY',3);
define('MANY_TO_MANY',4);
/**
+------------------------------------------------------------------------------
* ThinkPHP Model模型类
* 实现了ORM和ActiveRecords模式
+------------------------------------------------------------------------------
* @category Think
* @package Think
* @subpackage Core
* @author liu21st <liu21st@gmail.com>
* @version $Id$
+------------------------------------------------------------------------------
*/
class Model extends Think
{
// 操作状态
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 $tableSuffix = '';
// 模型名称
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;
/**
+----------------------------------------------------------
* 架构函数
* 取得DB类的实例对象 字段检查
+----------------------------------------------------------
* @param string $name 模型名称
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
*/
public function __construct($name='')
{
// 模型初始化
$this->_initialize();
// 获取模型名称
if(!empty($name)) {
$this->name = $name;
}elseif(empty($this->name)){
$this->name = $this->getModelName();
}
// 数据库初始化操作
// 获取数据库操作对象
// 当前模型有独立的数据库连接信息
$this->db = Db::getInstance(empty($this->connection)?'':$this->connection);
// 设置表前缀
$this->tablePrefix = $this->tablePrefix?$this->tablePrefix:C('DB_PREFIX');
$this->tableSuffix = $this->tableSuffix?$this->tableSuffix:C('DB_SUFFIX');
// 字段检测
if(!empty($this->name) && $this->autoCheckFields) $this->_checkTableInfo();
}
/**
+----------------------------------------------------------
* 自动检测数据表信息
+----------------------------------------------------------
* @access protected
+----------------------------------------------------------
* @return void
+----------------------------------------------------------
*/
protected function _checkTableInfo() {
// 如果不是Model类 自动记录数据表信息
// 只在第一次执行记录
if(empty($this->fields)) {
// 如果数据表字段没有定义则自动获取
if(C('DB_FIELDS_CACHE')) {
$this->fields = F('_fields/'.$this->name);
if(!$this->fields) $this->flush();
}else{
// 每次都会读取数据表信息
$this->flush();
}
}
}
/**
+----------------------------------------------------------
* 获取字段信息并缓存
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @return void
+----------------------------------------------------------
*/
public function flush() {
// 缓存不存在则查询数据表信息
$fields = $this->db->getFields($this->getTableName());
$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'))
// 永久缓存数据表信息
F('_fields/'.$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
+----------------------------------------------------------
* @param string $name 名称
* @param mixed $value 值
+----------------------------------------------------------
* @return void
+----------------------------------------------------------
*/
public function __set($name,$value) {
// 设置数据对象属性
$this->data[$name] = $value;
}
/**
+----------------------------------------------------------
* 获取数据对象的值
+----------------------------------------------------------
* @access public
+-----------------------------------