改进Model类

This commit is contained in:
thinkphp
2015-02-21 10:35:46 +08:00
parent 6ecc2963f1
commit d81c715dd5

View File

@@ -18,6 +18,8 @@ class Model {
const MODEL_BOTH = 3; // 包含上面两种方式 const MODEL_BOTH = 3; // 包含上面两种方式
// 当前数据库操作对象 // 当前数据库操作对象
protected $db = null; protected $db = null;
// 数据库对象池
private $_db = [];
// 主键名称 // 主键名称
protected $pk = 'id'; protected $pk = 'id';
// 数据表前缀 // 数据表前缀
@@ -188,7 +190,7 @@ class Model {
// 重置数据 // 重置数据
$this->data = []; $this->data = [];
}else{ }else{
$this->error = L('_DATA_TYPE_INVALID_'); $this->error = Lang::get('_DATA_TYPE_INVALID_');
return false; return false;
} }
} }
@@ -201,15 +203,22 @@ class Model {
} }
// 写入数据到数据库 // 写入数据到数据库
$result = $this->db->insert($data,$options,$replace); $result = $this->db->insert($data,$options,$replace);
if(false !== $result ) { if(false !== $result && is_numeric($result)) {
$pk = $this->getPk();
// 增加复合主键支持
if (is_array($pk)) return $result;
$insertId = $this->getLastInsID(); $insertId = $this->getLastInsID();
if($insertId) { if($insertId) {
// 自增主键返回插入ID // 自增主键返回插入ID
$data[$this->getPk()] = $insertId; $data[$pk] = $insertId;
$this->_after_insert($data,$options); if(false === $this->_after_insert($data,$options)){
return false;
}
return $insertId; return $insertId;
} }
$this->_after_insert($data,$options); if(false === $this->_after_insert($data,$options)){
return false;
}
} }
return $result; return $result;
} }
@@ -218,9 +227,9 @@ class Model {
// 插入成功后的回调方法 // 插入成功后的回调方法
protected function _after_insert($data,$options) {} protected function _after_insert($data,$options) {}
public function addAll($dataList,$options=array(),$replace=false){ public function addAll($dataList,$options=[],$replace=false){
if(empty($dataList)) { if(empty($dataList)) {
$this->error = L('_DATA_TYPE_INVALID_'); $this->error = Lang::get('_DATA_TYPE_INVALID_');
return false; return false;
} }
// 数据处理 // 数据处理
@@ -254,33 +263,54 @@ class Model {
// 重置数据 // 重置数据
$this->data = []; $this->data = [];
}else{ }else{
$this->error = L('_DATA_TYPE_INVALID_'); $this->error = Lang::get('_DATA_TYPE_INVALID_');
return false; return false;
} }
} }
// 数据处理 // 数据处理
$data = $this->_write_data($data); $data = $this->_write_data($data);
if(empty($data)){
// 没有数据则不执行
$this->error = Lang::get('_DATA_TYPE_INVALID_');
return false;
}
// 分析表达式 // 分析表达式
$options = $this->_parseOptions(); $options = $this->_parseOptions();
if(false === $this->_before_update($data,$options)) { $pk = $this->getPk();
return false;
}
if(!isset($options['where']) ) { if(!isset($options['where']) ) {
// 如果存在主键数据 则自动作为更新条件 // 如果存在主键数据 则自动作为更新条件
if(isset($data[$this->getPk()])) { if (is_string($pk) && isset($data[$pk])) {
$pk = $this->getPk(); $where[$pk] = $data[$pk];
$where[$pk] = $data[$pk];
$options['where'] = $where;
$pkValue = $data[$pk];
unset($data[$pk]); unset($data[$pk]);
}else{ } elseif (is_array($pk)) {
// 增加复合主键支持
foreach ($pk as $field) {
if(isset($data[$field])) {
$where[$field] = $data[$field];
} else {
// 如果缺少复合主键数据则不执行
$this->error = Lang::get('_OPERATION_WRONG_');
return false;
}
unset($data[$field]);
}
}
if(!isset($where)){
// 如果没有任何更新条件则不执行 // 如果没有任何更新条件则不执行
$this->error = Lang::get('_OPERATION_WRONG_'); $this->error = Lang::get('_OPERATION_WRONG_');
return false; return false;
} }else{
$options['where'] = $where;
}
} }
if(isset($options['where'][$pk])){
$pkValue = $options['where'][$pk];
}
if(false === $this->_before_update($data,$options)) {
return false;
}
$result = $this->db->update($data,$options); $result = $this->db->update($data,$options);
if(false !== $result) { if(false !== $result && is_numeric($result)) {
if(isset($pkValue)) $data[$pk] = $pkValue; if(isset($pkValue)) $data[$pk] = $pkValue;
$this->_after_update($data,$options); $this->_after_update($data,$options);
} }
@@ -298,29 +328,53 @@ class Model {
* @return mixed * @return mixed
*/ */
public function delete($options=[]) { public function delete($options=[]) {
$pk = $this->getPk();
if(empty($options) && empty($this->options['where'])) { if(empty($options) && empty($this->options['where'])) {
// 如果删除条件为空 则删除当前数据对象所对应的记录 // 如果删除条件为空 则删除当前数据对象所对应的记录
if(!empty($this->data) && isset($this->data[$this->getPk()])) if(!empty($this->data) && isset($this->data[$pk])){
return $this->delete($this->data[$this->getPk()]); return $this->delete($this->data[$pk]);
else }else{
return false; return false;
}
} }
if(is_numeric($options) || is_string($options)) { if(is_numeric($options) || is_string($options)) {
// 根据主键删除记录 // 根据主键删除记录
$pk = $this->getPk();
if(strpos($options,',')) { if(strpos($options,',')) {
$where[$pk] = ['IN', $options]; $where[$pk] = ['IN', $options];
}else{ }else{
$where[$pk] = $options; $where[$pk] = $options;
} }
$pkValue = $where[$pk];
$options = []; $options = [];
$options['where'] = $where; $options['where'] = $where;
} }
// 根据复合主键删除记录
if (is_array($options) && (count($options) > 0) && is_array($pk)) {
$count = 0;
foreach (array_keys($options) as $key) {
if (is_int($key)) $count++;
}
if ($count == count($pk)) {
$i = 0;
foreach ($pk as $field) {
$where[$field] = $options[$i];
unset($options[$i++]);
}
$options['where'] = $where;
} else {
return false;
}
}
// 分析表达式 // 分析表达式
$options = $this->_parseOptions($options); $options = $this->_parseOptions($options);
$result= $this->db->delete($options); if(empty($options['where'])){
if(false !== $result) { // 如果条件为空 不进行删除操作 除非设置 1=1
return false;
}
if(isset($options['where'][$pk])){
$pkValue = $options['where'][$pk];
}
$result = $this->db->delete($options);
if(false !== $result && is_numeric($result)) {
$data = []; $data = [];
if(isset($pkValue)) $data[$pk] = $pkValue; if(isset($pkValue)) $data[$pk] = $pkValue;
$this->_after_delete($data,$options); $this->_after_delete($data,$options);
@@ -338,9 +392,9 @@ class Model {
* @return mixed * @return mixed
*/ */
public function select($options=[]) { public function select($options=[]) {
$pk = $this->getPk();
if(is_string($options) || is_numeric($options)) { if(is_string($options) || is_numeric($options)) {
// 根据主键查询 // 根据主键查询
$pk = $this->getPk();
if(strpos($options,',')) { if(strpos($options,',')) {
$where[$pk] = ['IN',$options]; $where[$pk] = ['IN',$options];
}else{ }else{
@@ -348,8 +402,24 @@ class Model {
} }
$options = []; $options = [];
$options['where'] = $where; $options['where'] = $where;
}elseif (is_array($options) && (count($options) > 0) && is_array($pk)) {
// 根据复合主键查询
$count = 0;
foreach (array_keys($options) as $key) {
if (is_int($key)) $count++;
}
if ($count == count($pk)) {
$i = 0;
foreach ($pk as $field) {
$where[$field] = $options[$i];
unset($options[$i++]);
}
$options['where'] = $where;
} else {
return false;
}
}elseif(false === $options){ // 用于子查询 不查询只返回SQL }elseif(false === $options){ // 用于子查询 不查询只返回SQL
return $this->buildSql(); $options['fetch_sql'] = true;
} }
// 分析表达式 // 分析表达式
@@ -358,7 +428,7 @@ class Model {
if(isset($options['cache'])){ if(isset($options['cache'])){
$cache = $options['cache']; $cache = $options['cache'];
$key = is_string($cache['key'])?$cache['key']:md5(serialize($options)); $key = is_string($cache['key'])?$cache['key']:md5(serialize($options));
$data = S($key,'',$cache); $data = Cache::get($key,'',$cache);
if(false !== $data){ if(false !== $data){
return $data; return $data;
} }
@@ -390,7 +460,7 @@ class Model {
} }
if(isset($cache)){ if(isset($cache)){
S($key,$resultSet,$cache); Cache::set($key,$resultSet,$cache);
} }
return $resultSet; return $resultSet;
@@ -496,11 +566,30 @@ class Model {
* @return mixed * @return mixed
*/ */
public function find($options=[]) { public function find($options=[]) {
$pk = $this->getPk();
if(is_numeric($options) || is_string($options)) { if(is_numeric($options) || is_string($options)) {
$where[$this->getPk()] = $options; $where[$pk] = $options;
$options = []; $options = [];
$options['where'] = $where; $options['where'] = $where;
} }
// 根据复合主键查找记录
if (is_array($options) && is_array($pk) && (count($options) > 0) ) {
// 根据复合主键查询
$count = 0;
foreach (array_keys($options) as $key) {
if (is_int($key)) $count++;
}
if ($count == count($pk)) {
$i = 0;
foreach ($pk as $field) {
$where[$field] = $options[$i];
unset($options[$i++]);
}
$options['where'] = $where;
} else {
return false;
}
}
// 总是查找一条记录 // 总是查找一条记录
$options['limit'] = 1; $options['limit'] = 1;
// 分析表达式 // 分析表达式
@@ -509,7 +598,7 @@ class Model {
if(isset($options['cache'])){ if(isset($options['cache'])){
$cache = $options['cache']; $cache = $options['cache'];
$key = is_string($cache['key'])?$cache['key']:md5(serialize($options)); $key = is_string($cache['key'])?$cache['key']:md5(serialize($options));
$data = S($key,'',$cache); $data = Cache::get($key,'',$cache);
if(false !== $data){ if(false !== $data){
$this->data = $data; $this->data = $data;
return $data; return $data;
@@ -530,7 +619,7 @@ class Model {
// 数据对象赋值 // 数据对象赋值
$this->data = $data; $this->data = $data;
if(isset($cache)){ if(isset($cache)){
S($key,$data,$cache); Cache::set($key,$data,$cache);
} }
return $this->data; return $this->data;
} }
@@ -573,7 +662,7 @@ class Model {
} }
// 验证数据 // 验证数据
if(empty($data) || !is_array($data)) { if(empty($data) || !is_array($data)) {
$this->error = L('_DATA_TYPE_INVALID_'); $this->error = Lang::get('_DATA_TYPE_INVALID_');
return false; return false;
} }
@@ -620,24 +709,20 @@ class Model {
if(''===$linkNum && $this->db) { if(''===$linkNum && $this->db) {
return $this->db; return $this->db;
} }
static $_linkNum = []; if(!isset($this->_db[$linkNum])) {
static $_db = [];
if(!isset($_db[$linkNum]) || (isset($_db[$linkNum]) && $config && $_linkNum[$linkNum]!=$config) ) {
// 创建一个新的实例 // 创建一个新的实例
if(!empty($config) && is_string($config) && false === strpos($config,'/')) { // 支持读取配置参数 if(!empty($config) && is_string($config) && false === strpos($config,'/')) { // 支持读取配置参数
$config = C($config); $config = Config::get($config);
} }
$_db[$linkNum] = Db::instance($config); $this->_db[$linkNum] = Db::instance($config);
}elseif(null === $config){ }elseif(null === $config){
$_db[$linkNum]->close(); // 关闭数据库连接 $this->_db[$linkNum]->close(); // 关闭数据库连接
unset($_db[$linkNum]); unset($this->_db[$linkNum]);
return ; return ;
} }
// 记录连接信息
$_linkNum[$linkNum] = $config;
// 切换数据库连接 // 切换数据库连接
$this->db = $_db[$linkNum]; $this->db = $this->_db[$linkNum];
$this->_after_db(); $this->_after_db();
return $this; return $this;
} }
@@ -737,7 +822,18 @@ class Model {
// 记录字段类型 // 记录字段类型
$type[$key] = $val['type']; $type[$key] = $val['type'];
if($val['primary']) { if($val['primary']) {
$this->fields['_pk'] = $key; // 增加复合主键支持
if (!empty($this->fields['_pk'])) {
if (is_string($this->fields['_pk'])) {
$this->pk = array($this->fields['_pk']);
$this->fields['_pk'] = $this->pk;
}
$this->pk[] = $key;
$this->fields['_pk'][] = $key;
} else {
$this->pk = $key;
$this->fields['_pk'] = $key;
}
} }
} }
// 记录字段类型信息 // 记录字段类型信息
@@ -756,24 +852,56 @@ class Model {
* SQL查询 * SQL查询
* @access public * @access public
* @param string $sql SQL指令 * @param string $sql SQL指令
* @param array $bind 参数绑定 * @param mixed $parse 是否需要解析SQL
* @return mixed * @return mixed
*/ */
public function query($sql,$bind=[]) { public function query($sql,$parse=false) {
$sql = strtr($sql,['__TABLE__'=>$this->getTableName(),'__PREFIX__'=>$this->tablePrefix]); if(!is_bool($parse) && !is_array($parse)) {
return $this->db->query($sql,$bind); $parse = func_get_args();
array_shift($parse);
}
$sql = $this->parseSql($sql,$parse);
return $this->db->query($sql);
} }
/** /**
* 执行SQL语句 * 执行SQL语句
* @access public * @access public
* @param string $sql SQL指令 * @param string $sql SQL指令
* @param array $bind 参数绑定 * @param mixed $parse 是否需要解析SQL
* @return false | integer * @return false | integer
*/ */
public function execute($sql,$bind=[]) { public function execute($sql,$parse=false) {
$sql = strtr($sql,['__TABLE__'=>$this->getTableName(),'__PREFIX__'=>$this->tablePrefix]); if(!is_bool($parse) && !is_array($parse)) {
return $this->db->execute($sql,$bind); $parse = func_get_args();
array_shift($parse);
}
$sql = $this->parseSql($sql,$parse);
return $this->db->execute($sql);
}
/**
* 解析SQL语句
* @access public
* @param string $sql SQL指令
* @param boolean $parse 是否需要解析SQL
* @return string
*/
protected function parseSql($sql,$parse) {
// 分析表达式
if(true === $parse) {
$options = $this->_parseOptions();
$sql = $this->db->parseSql($sql,$options);
}elseif(is_array($parse)){ // SQL预处理
$parse = array_map(array($this->db,'escapeString'),$parse);
$sql = vsprintf($sql,$parse);
}else{
$sql = strtr($sql,array('__TABLE__'=>$this->getTableName(),'__PREFIX__'=>$this->tablePrefix));
$prefix = $this->tablePrefix;
$sql = preg_replace_callback("/__([A-Z0-9_-]+)__/sU", function($match) use($prefix){ return $prefix.strtolower($match[1]);}, $sql);
}
$this->db->setModel($this->name);
return $sql;
} }
/** /**
@@ -791,7 +919,7 @@ class Model {
}elseif(is_string($data)){ }elseif(is_string($data)){
parse_str($data,$data); parse_str($data,$data);
}elseif(!is_array($data)){ }elseif(!is_array($data)){
E(L('_DATA_TYPE_INVALID_')); E(Lang::get('_DATA_TYPE_INVALID_'));
} }
$this->data = $data; $this->data = $data;
return $this; return $this;
@@ -848,7 +976,7 @@ class Model {
$options = $union; $options = $union;
} }
}else{ }else{
E(L('_DATA_TYPE_INVALID_')); E(Lang::get('_DATA_TYPE_INVALID_'));
} }
$this->options['union'][] = $options; $this->options['union'][] = $options;
return $this; return $this;
@@ -1104,6 +1232,28 @@ class Model {
return $this; return $this;
} }
/**
* 对数据集进行索引
* @access public
* @param string $index 索引名称
* @return Model
*/
public function index($index){
$this->options['index'] = $index;
return $this;
}
/**
* 指定强制索引
* @access public
* @param string $force 索引名称
* @return Model
*/
public function force($force){
$this->options['force'] = $force;
return $this;
}
/** /**
* 参数绑定 * 参数绑定
* @access public * @access public