改进Model类的db方法 并增加query属性

This commit is contained in:
thinkphp
2016-05-18 22:33:59 +08:00
parent 67500bc3c9
commit b4d90ade7a
3 changed files with 75 additions and 56 deletions

View File

@@ -34,6 +34,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
protected $name; protected $name;
// 数据表名称 // 数据表名称
protected $table; protected $table;
// 查询对象
protected $query;
// 回调事件 // 回调事件
protected static $event = []; protected static $event = [];
@@ -99,10 +101,14 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} else { } else {
$this->data = $data; $this->data = $data;
} }
if (empty($this->name)) { if (empty($this->name)) {
$this->name = basename(str_replace('\\', '/', get_class($this))); $this->name = basename(str_replace('\\', '/', get_class($this)));
} }
// 当前模型的查询对象
$this->query = $this->db();
// 执行初始化操作
$this->initialize(); $this->initialize();
} }
@@ -233,7 +239,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
public function getPk($table = '') public function getPk($table = '')
{ {
if (empty($this->pk)) { if (empty($this->pk)) {
$this->pk = self::db()->getTableInfo($table, 'pk'); $this->pk = $this->query->getTableInfo($table, 'pk');
} }
return $this->pk; return $this->pk;
} }
@@ -301,7 +307,6 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
return false; return false;
} }
$db = self::db();
if ($this->isUpdate) { if ($this->isUpdate) {
// 自动更新 // 自动更新
$this->autoCompleteData($this->update); $this->autoCompleteData($this->update);
@@ -330,7 +335,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} }
} }
$result = $db->where($where)->update($data); $result = $this->query->where($where)->update($data);
// 更新回调 // 更新回调
$this->trigger('after_update', $this); $this->trigger('after_update', $this);
@@ -347,11 +352,11 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
return false; return false;
} }
$result = $db->insert($this->data); $result = $this->query->insert($this->data);
// 获取自动增长主键 // 获取自动增长主键
if ($result && $getId) { if ($result && $getId) {
$insertId = $db->getLastInsID(); $insertId = $this->query->getLastInsID();
$pk = $this->getPk(); $pk = $this->getPk();
if (is_string($pk) && $insertId) { if (is_string($pk) && $insertId) {
$this->data[$pk] = $insertId; $this->data[$pk] = $insertId;
@@ -443,7 +448,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
return false; return false;
} }
$result = self::db()->delete($this->data); $result = $this->query->delete($this->data);
$this->trigger('after_delete', $this); $this->trigger('after_delete', $this);
return $result; return $result;
@@ -648,15 +653,16 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
*/ */
public static function destroy($data) public static function destroy($data)
{ {
$db = self::db(); $model = new static();
$query = $model->db();
if (is_array($data) && key($data) !== 0) { if (is_array($data) && key($data) !== 0) {
$db->where($data); $query->where($data);
$data = []; $data = [];
} elseif ($data instanceof \Closure) { } elseif ($data instanceof \Closure) {
call_user_func_array($data, [ & $db]); call_user_func_array($data, [ & $query]);
$data = []; $data = [];
} }
$resultSet = $db->select($data); $resultSet = $query->select($data);
$result = false; $result = false;
if ($resultSet) { if ($resultSet) {
foreach ($resultSet as $data) { foreach ($resultSet as $data) {
@@ -676,9 +682,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
public static function scope($name, $params = []) public static function scope($name, $params = [])
{ {
$model = new static(); $model = new static();
$class = self::db(); $query = $model->db();
if ($name instanceof \Closure) { if ($name instanceof \Closure) {
call_user_func_array($name, [ & $class, $params]); call_user_func_array($name, [ & $query, $params]);
} elseif ($name instanceof Query) { } elseif ($name instanceof Query) {
return $name; return $name;
} else { } else {
@@ -686,7 +692,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
foreach ($names as $scope) { foreach ($names as $scope) {
$method = 'scope' . $scope; $method = 'scope' . $scope;
if (method_exists($model, $method)) { if (method_exists($model, $method)) {
$model->$method($class, $params); $model->$method($query, $params);
} }
} }
} }
@@ -704,10 +710,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
*/ */
public static function has($relation, $operator = '>=', $count = 1, $id = '*') public static function has($relation, $operator = '>=', $count = 1, $id = '*')
{ {
$class = new static(); $model = new static();
$info = $class->$relation()->getRelationInfo(); $info = $model->$relation()->getRelationInfo();
$table = $info['model']::getTable(); $table = $info['model']::getTable();
return self::db()->alias('a') return $model->db()->alias('a')
->join($table . ' b', 'a.' . $info['localKey'] . '=b.' . $info['foreignKey']) ->join($table . ' b', 'a.' . $info['localKey'] . '=b.' . $info['foreignKey'])
->group('b.' . $info['foreignKey']) ->group('b.' . $info['foreignKey'])
->having('count(' . $id . ')' . $operator . $count); ->having('count(' . $id . ')' . $operator . $count);
@@ -722,8 +728,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
*/ */
public static function hasWhere($relation, $where = []) public static function hasWhere($relation, $where = [])
{ {
$class = new static(); $model = new static();
$info = $class->$relation()->getRelationInfo(); $info = $model->$relation()->getRelationInfo();
$table = $info['model']::getTable(); $table = $info['model']::getTable();
if (is_array($where)) { if (is_array($where)) {
foreach ($where as $key => $val) { foreach ($where as $key => $val) {
@@ -733,7 +739,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} }
} }
} }
return self::db()->alias('a') return $model->db()->alias('a')
->field('a.*') ->field('a.*')
->join($table . ' b', 'a.' . $info['localKey'] . '=b.' . $info['foreignKey']) ->join($table . ' b', 'a.' . $info['localKey'] . '=b.' . $info['foreignKey'])
->where($where); ->where($where);
@@ -870,28 +876,25 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} }
/** /**
* 初始化数据库对象 * 获取当前模型的数据库查询对象
* @access protected * @access public
* @return \think\db\Query * @return \think\db\Query
*/ */
protected static function db() public function db()
{ {
$model = get_called_class(); $model = get_called_class();
if (!isset(self::$links[$model])) { if (!isset(self::$links[$model])) {
$class = new static();
// 设置当前模型 确保查询返回模型对象 // 设置当前模型 确保查询返回模型对象
self::$links[$model] = Db::connect($class->connection)->model($model); $query = Db::connect($this->connection)->model($model);
// 设置当前数据表和模型名 // 设置当前数据表和模型名
if (!empty($class->table)) { if (!empty($this->table)) {
self::$links[$model]->setTable($class->table); $query->setTable($this->table);
} else { } else {
$name = !empty($class->name) ? $class->name : basename(str_replace('\\', '/', $model)); $query->name($this->name);
self::$links[$model]->name($name);
} }
self::$links[$model] = $query;
} }
// 返回当前模型的数据库查询对象 // 返回当前模型的数据库查询对象
return self::$links[$model]; return self::$links[$model];
} }
@@ -901,18 +904,23 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
if (method_exists($this, 'scope' . $method)) { if (method_exists($this, 'scope' . $method)) {
// 动态调用命名范围 // 动态调用命名范围
$method = 'scope' . $method; $method = 'scope' . $method;
$class = self::db(); array_unshift($args, $this->query);
array_unshift($args, $class);
call_user_func_array([$this, $method], $args); call_user_func_array([$this, $method], $args);
return $this; return $this;
} else { } else {
return call_user_func_array([self::db(), $method], $args); return call_user_func_array([$this->query, $method], $args);
} }
} }
public static function __callStatic($method, $params) public static function __callStatic($method, $params)
{ {
return call_user_func_array([self::db(), $method], $params); $model = get_called_class();
if (!isset(self::$links[$model])) {
$class = new static();
self::$links[$model] = $class->db();
}
$query = self::$links[$model];
return call_user_func_array([$query, $method], $params);
} }
/** /**
@@ -926,7 +934,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
{ {
if (is_null($this->fieldType)) { if (is_null($this->fieldType)) {
// 获取字段类型信息并缓存 // 获取字段类型信息并缓存
$this->fieldType = self::db()->getTableInfo('', 'type'); $this->fieldType = $this->query->getTableInfo('', 'type');
} }
if (is_null($value) && $this->autoWriteTimestamp && in_array($name, [$this->createTime, $this->updateTime, $this->deleteTime])) { if (is_null($value) && $this->autoWriteTimestamp && in_array($name, [$this->createTime, $this->updateTime, $this->deleteTime])) {
// 自动写入的时间戳字段 // 自动写入的时间戳字段

View File

@@ -61,14 +61,14 @@ class Merge extends Model
{ {
$class = new static(); $class = new static();
$master = $class->name; $master = $class->name;
$fields = self::getModelField($master, '', $class->mapFields); $fields = self::getModelField($query, $master, '', $class->mapFields);
$query->alias($master)->field($fields); $query->alias($master)->field($fields);
foreach (static::$relationModel as $key => $model) { foreach (static::$relationModel as $key => $model) {
$name = is_int($key) ? $model : $key; $name = is_int($key) ? $model : $key;
$table = is_int($key) ? $query->getTable($name) : $model; $table = is_int($key) ? $query->getTable($name) : $model;
$query->join($table . ' ' . $name, $name . '.' . $class->fk . '=' . $master . '.' . $class->getPk()); $query->join($table . ' ' . $name, $name . '.' . $class->fk . '=' . $master . '.' . $class->getPk());
$fields = self::getModelField($name, $table, $class->mapFields); $fields = self::getModelField($query, $name, $table, $class->mapFields);
$query->field($fields); $query->field($fields);
} }
return $query; return $query;
@@ -77,15 +77,16 @@ class Merge extends Model
/** /**
* 获取关联模型的字段 并解决混淆 * 获取关联模型的字段 并解决混淆
* @access protected * @access protected
* @param \think\db\Query $query 查询对象
* @param string $name 模型名称 * @param string $name 模型名称
* @param string $table 关联表名称 * @param string $table 关联表名称
* @param array $map 字段映射 * @param array $map 字段映射
* @return array * @return array
*/ */
protected static function getModelField($name, $table = '', $map = []) protected static function getModelField($query, $name, $table = '', $map = [])
{ {
// 获取模型的字段信息 // 获取模型的字段信息
$fields = self::db()->getTableInfo($table, 'fields'); $fields = $query->getTableInfo($table, 'fields');
$array = []; $array = [];
foreach ($fields as $field) { foreach ($fields as $field) {
if ($key = array_search($name . '.' . $field, $map)) { if ($key = array_search($name . '.' . $field, $map)) {
@@ -163,11 +164,16 @@ class Merge extends Model
} }
// 数据自动完成 // 数据自动完成
$this->autoCompleteData($this->auto); $this->autoCompleteData($this->auto);
// 自动写入更新时间
if ($this->autoWriteTimestamp) {
$this->__set($this->updateTime, null);
}
// 处理模型数据 // 处理模型数据
$data = $this->parseData($this->name, $this->data); $data = $this->parseData($this->name, $this->data);
$db = self::db(); $this->query->startTrans('merge_save_' . $this->name);
$db->startTrans('merge_save_' . $this->name);
try { try {
if ($this->isUpdate) { if ($this->isUpdate) {
// 自动写入 // 自动写入
@@ -178,15 +184,15 @@ class Merge extends Model
} }
// 写入主表数据 // 写入主表数据
$result = $db->strict(false)->update($data); $result = $this->query->strict(false)->update($data);
// 写入附表数据 // 写入附表数据
foreach (static::$relationModel as $key => $model) { foreach (static::$relationModel as $key => $model) {
$name = is_int($key) ? $model : $key; $name = is_int($key) ? $model : $key;
$table = is_int($key) ? $db->getTable($model) : $model; $table = is_int($key) ? $this->query->getTable($model) : $model;
// 处理关联模型数据 // 处理关联模型数据
$data = $this->parseData($name, $this->data); $data = $this->parseData($name, $this->data);
$query = clone $db; $query = clone $this->query;
$query->table($table)->strict(false)->where($this->fk, $this->data[$this->getPk()])->update($data); $query->table($table)->strict(false)->where($this->fk, $this->data[$this->getPk()])->update($data);
} }
// 新增回调 // 新增回调
@@ -195,6 +201,11 @@ class Merge extends Model
// 自动写入 // 自动写入
$this->autoCompleteData($this->insert); $this->autoCompleteData($this->insert);
// 自动写入创建时间
if ($this->autoWriteTimestamp) {
$this->__set($this->createTime, null);
}
if (false === $this->trigger('before_insert', $this)) { if (false === $this->trigger('before_insert', $this)) {
return false; return false;
} }
@@ -209,10 +220,10 @@ class Merge extends Model
// 写入附表数据 // 写入附表数据
foreach (static::$relationModel as $key => $model) { foreach (static::$relationModel as $key => $model) {
$name = is_int($key) ? $model : $key; $name = is_int($key) ? $model : $key;
$table = is_int($key) ? $db->getTable($model) : $model; $table = is_int($key) ? $this->query->getTable($model) : $model;
// 处理关联模型数据 // 处理关联模型数据
$data = $this->parseData($name, $this->data, true); $data = $this->parseData($name, $this->data, true);
$query = clone $db; $query = clone $this->query;
$query->table($table)->strict(false)->insert($data); $query->table($table)->strict(false)->insert($data);
} }
$result = $insertId; $result = $insertId;
@@ -220,10 +231,10 @@ class Merge extends Model
// 新增回调 // 新增回调
$this->trigger('after_insert', $this); $this->trigger('after_insert', $this);
} }
$db->commit('merge_save_' . $this->name); $this->query->commit('merge_save_' . $this->name);
return $result; return $result;
} catch (\PDOException $e) { } catch (\PDOException $e) {
$db->rollback(); $this->query->rollback();
return false; return false;
} }
} }
@@ -238,26 +249,26 @@ class Merge extends Model
if (false === $this->trigger('before_delete', $this)) { if (false === $this->trigger('before_delete', $this)) {
return false; return false;
} }
$db = self::db();
$db->startTrans('merge_delete_' . $this->name); $this->query->startTrans('merge_delete_' . $this->name);
try { try {
$result = $db->delete($this->data); $result = $this->query->delete($this->data);
if ($result) { if ($result) {
// 获取主键数据 // 获取主键数据
$pk = $this->data[$this->getPk()]; $pk = $this->data[$this->getPk()];
// 删除关联数据 // 删除关联数据
foreach (static::$relationModel as $key => $model) { foreach (static::$relationModel as $key => $model) {
$table = is_int($key) ? $db->getTable($model) : $model; $table = is_int($key) ? $this->query->getTable($model) : $model;
$query = clone $db; $query = clone $this->query;
$query->table($table)->where($this->fk, $pk)->delete(); $query->table($table)->where($this->fk, $pk)->delete();
} }
} }
$this->trigger('after_delete', $this); $this->trigger('after_delete', $this);
$db->commit('merge_delete_' . $this->name); $this->query->commit('merge_delete_' . $this->name);
return $result; return $result;
} catch (\PDOException $e) { } catch (\PDOException $e) {
$db->rollback(); $this->query->rollback();
return false; return false;
} }
} }

View File

@@ -593,7 +593,7 @@ class Relation
{ {
if ($this->model) { if ($this->model) {
$model = new $this->model; $model = new $this->model;
$db = $model::db(); $db = $model->db();
if (self::HAS_MANY == $this->type && isset($this->parent->{$this->localKey})) { if (self::HAS_MANY == $this->type && isset($this->parent->{$this->localKey})) {
// 关联查询带入关联条件 // 关联查询带入关联条件
$db->where($this->foreignKey, $this->parent->{$this->localKey}); $db->where($this->foreignKey, $this->parent->{$this->localKey});