更新tp5内核

This commit is contained in:
2018-01-02 23:03:31 +08:00
parent 590696a06b
commit 3818619504
99 changed files with 3362 additions and 2006 deletions
+165 -77
View File
@@ -2,7 +2,7 @@
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
@@ -11,6 +11,7 @@
namespace think;
use BadMethodCallException;
use InvalidArgumentException;
use think\db\Query;
use think\exception\ValidateException;
@@ -56,6 +57,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
protected $pk;
// 数据表字段信息 留空则自动获取
protected $field = [];
// 数据排除字段
protected $except = [];
// 数据废弃字段
protected $disuse = [];
// 只读字段
protected $readonly = [];
// 显示属性
@@ -89,6 +94,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
protected $type = [];
// 是否为更新数据
protected $isUpdate = false;
// 是否强制更新所有数据
protected $force = false;
// 更新条件
protected $updateWhere;
// 验证失败是否抛出异常
@@ -121,6 +128,16 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} else {
$this->data = $data;
}
if ($this->disuse) {
// 废弃字段
foreach ((array) $this->disuse as $key) {
if (array_key_exists($key, $this->data)) {
unset($this->data[$key]);
}
}
}
// 记录原始数据
$this->origin = $this->data;
@@ -261,7 +278,6 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
public function setParent($model)
{
$this->parent = $model;
return $this;
}
@@ -336,6 +352,18 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
return $this;
}
/**
* 更新是否强制写入数据 而不做比较
* @access public
* @param bool $force
* @return $this
*/
public function force($force = true)
{
$this->force = $force;
return $this;
}
/**
* 修改器 设置数据对象值
* @access public
@@ -353,7 +381,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
// 检测修改器
$method = 'set' . Loader::parseName($name, 1) . 'Attr';
if (method_exists($this, $method)) {
$value = $this->$method($value, array_merge($this->data, $data));
$value = $this->$method($value, array_merge($this->data, $data), $this->relation);
} elseif (isset($this->type[$name])) {
// 类型转换
$value = $this->writeTransform($value, $this->type[$name]);
@@ -532,7 +560,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
// 检测属性获取器
$method = 'get' . Loader::parseName($name, 1) . 'Attr';
if (method_exists($this, $method)) {
$value = $this->$method($value, $this->data);
$value = $this->$method($value, $this->data, $this->relation);
} elseif (isset($this->type[$name])) {
// 类型转换
$value = $this->readTransform($value, $this->type[$name]);
@@ -567,6 +595,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
* @access public
* @param Relation $modelRelation 模型关联对象
* @return mixed
* @throws BadMethodCallException
*/
protected function getRelationData(Relation $modelRelation)
{
@@ -574,7 +603,11 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
$value = $this->parent;
} else {
// 首先获取关联数据
$value = $modelRelation->getRelation();
if (method_exists($modelRelation, 'getRelation')) {
$value = $modelRelation->getRelation();
} else {
throw new BadMethodCallException('method not exists:' . get_class($modelRelation) . '-> getRelation');
}
}
return $value;
}
@@ -686,7 +719,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
if (isset($this->data[$key])) {
throw new Exception('bind attr has exists:' . $key);
} else {
$this->data[$key] = $model->$attr;
$this->data[$key] = $model->getAttr($attr);
}
}
}
@@ -820,7 +853,29 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
$relation = $this->getAttr($key);
$item[$key] = $relation->append([$attr])->toArray();
} else {
$item[$name] = $this->getAttr($name);
$relation = Loader::parseName($name, 1, false);
if (method_exists($this, $relation)) {
$modelRelation = $this->$relation();
$value = $this->getRelationData($modelRelation);
if (method_exists($modelRelation, 'getBindAttr')) {
$bindAttr = $modelRelation->getBindAttr();
if ($bindAttr) {
foreach ($bindAttr as $key => $attr) {
$key = is_numeric($key) ? $attr : $key;
if (isset($this->data[$key])) {
throw new Exception('bind attr has exists:' . $key);
} else {
$item[$key] = $value ? $value->getAttr($attr) : null;
}
}
continue;
}
}
$item[$name] = $value;
} else {
$item[$name] = $this->getAttr($name);
}
}
}
}
@@ -927,6 +982,11 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
*/
public function save($data = [], $where = [], $sequence = null)
{
if (is_string($data)) {
$sequence = $data;
$data = [];
}
if (!empty($data)) {
// 数据自动验证
if (!$this->validateData($data)) {
@@ -937,7 +997,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
$this->setAttr($key, $value, $data);
}
if (!empty($where)) {
$this->isUpdate = true;
$this->isUpdate = true;
$this->updateWhere = $where;
}
}
@@ -1009,12 +1070,17 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
}
}
if (is_string($pk) && isset($data[$pk])) {
if (!isset($where[$pk])) {
unset($where);
$where[$pk] = $data[$pk];
$array = [];
foreach ((array) $pk as $key) {
if (isset($data[$key])) {
$array[$key] = $data[$key];
unset($data[$key]);
}
unset($data[$pk]);
}
if (!empty($array)) {
$where = $array;
}
// 检测字段
@@ -1056,16 +1122,17 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
// 检测字段
$allowFields = $this->checkAllowField(array_merge($this->auto, $this->insert));
if (!empty($allowFields)) {
$result = $this->getQuery()->strict(false)->field($allowFields)->insert($this->data);
$result = $this->getQuery()->strict(false)->field($allowFields)->insert($this->data, false, false, $sequence);
} else {
$result = $this->getQuery()->insert($this->data);
$result = $this->getQuery()->insert($this->data, false, false, $sequence);
}
// 获取自动增长主键
if ($result && is_string($pk) && (!isset($this->data[$pk]) || '' == $this->data[$pk])) {
$insertId = $this->getQuery()->getLastInsID($sequence);
if ($insertId) {
$this->data[$pk] = $insertId;
if ($result && $insertId = $this->getQuery()->getLastInsID($sequence)) {
foreach ((array) $pk as $key) {
if (!isset($this->data[$key]) || '' == $this->data[$key]) {
$this->data[$key] = $insertId;
}
}
}
@@ -1094,19 +1161,26 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
protected function checkAllowField($auto = [])
{
if (!empty($this->field)) {
if (!empty($this->origin)) {
$this->field = array_keys($this->origin);
$field = $this->field;
} elseif (true === $this->field) {
$this->field = $this->getQuery()->getTableInfo('', 'fields');
$field = $this->field;
} else {
$field = array_merge($this->field, $auto);
if (true === $this->field) {
$this->field = $this->getQuery()->getTableInfo('', 'fields');
$field = $this->field;
} elseif (!empty($this->field)) {
$field = array_merge($this->field, $auto);
if ($this->autoWriteTimestamp) {
array_push($field, $this->createTime, $this->updateTime);
}
} elseif (!empty($this->except)) {
$fields = $this->getQuery()->getTableInfo('', 'fields');
$field = array_diff($fields, (array) $this->except);
$this->field = $field;
} else {
$field = [];
}
if ($this->disuse) {
// 废弃字段
$field = array_diff($field, (array) $this->disuse);
}
return $field;
}
@@ -1132,12 +1206,16 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
*/
public function getChangedData()
{
$data = array_udiff_assoc($this->data, $this->origin, function ($a, $b) {
if ((empty($b) || empty($b)) && $a !== $b) {
return 1;
}
return is_object($a) || $a != $b ? 1 : 0;
});
if ($this->force) {
$data = $this->data;
} else {
$data = array_udiff_assoc($this->data, $this->origin, function ($a, $b) {
if ((empty($a) || empty($b)) && $a !== $b) {
return 1;
}
return is_object($a) || $a != $b ? 1 : 0;
});
}
if (!empty($this->readonly)) {
// 只读字段不允许更新
@@ -1162,16 +1240,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
*/
public function setInc($field, $step = 1, $lazyTime = 0)
{
// 删除条件
$pk = $this->getPk();
if (is_string($pk) && isset($this->data[$pk])) {
$where = [$pk => $this->data[$pk]];
} elseif (!empty($this->updateWhere)) {
$where = $this->updateWhere;
} else {
$where = null;
}
// 更新条件
$where = $this->getWhere();
$result = $this->getQuery()->where($where)->setInc($field, $step, $lazyTime);
if (true !== $result) {
@@ -1191,6 +1261,23 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
* @throws Exception
*/
public function setDec($field, $step = 1, $lazyTime = 0)
{
// 更新条件
$where = $this->getWhere();
$result = $this->getQuery()->where($where)->setDec($field, $step, $lazyTime);
if (true !== $result) {
$this->data[$field] -= $step;
}
return $result;
}
/**
* 获取更新条件
* @access protected
* @return mixed
*/
protected function getWhere()
{
// 删除条件
$pk = $this->getPk();
@@ -1202,13 +1289,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} else {
$where = null;
}
$result = $this->getQuery()->where($where)->setDec($field, $step, $lazyTime);
if (true !== $result) {
$this->data[$field] -= $step;
}
return $result;
return $where;
}
/**
@@ -1240,14 +1321,14 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
$auto = true;
}
foreach ($dataSet as $key => $data) {
if (!empty($auto) && isset($data[$pk])) {
if ($this->isUpdate || (!empty($auto) && isset($data[$pk]))) {
$result[$key] = self::update($data, [], $this->field);
} else {
$result[$key] = self::create($data, $this->field);
}
}
$db->commit();
return $result;
return $this->toCollection($result);
} catch (\Exception $e) {
$db->rollback();
throw $e;
@@ -1257,7 +1338,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
/**
* 设置允许写入的字段
* @access public
* @param mixed $field 允许写入的字段 如果为true只允许写入数据表字段
* @param string|array $field 允许写入的字段 如果为true只允许写入数据表字段
* @return $this
*/
public function allowField($field)
@@ -1269,6 +1350,21 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
return $this;
}
/**
* 设置排除写入的字段
* @access public
* @param string|array $field 排除允许写入的字段
* @return $this
*/
public function except($field)
{
if (is_string($field)) {
$field = explode(',', $field);
}
$this->except = $field;
return $this;
}
/**
* 设置只读字段
* @access public
@@ -1336,14 +1432,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
}
// 删除条件
$pk = $this->getPk();
if (is_string($pk) && isset($this->data[$pk])) {
$where = [$pk => $this->data[$pk]];
} elseif (!empty($this->updateWhere)) {
$where = $this->updateWhere;
} else {
$where = null;
}
$where = $this->getWhere();
// 删除当前模型数据
$result = $this->getQuery()->where($where)->delete();
@@ -1614,14 +1703,14 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
{
$model = new static();
$query = $model->db();
if (is_array($data) && key($data) !== 0) {
if (empty($data) && 0 !== $data) {
return 0;
} elseif (is_array($data) && key($data) !== 0) {
$query->where($data);
$data = null;
} elseif ($data instanceof \Closure) {
call_user_func_array($data, [ & $query]);
$data = null;
} elseif (empty($data) && 0 !== $data) {
return 0;
}
$resultSet = $query->select($data);
$count = 0;
@@ -1668,7 +1757,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
* 设置是否使用全局查询范围
* @param bool $use 是否启用全局查询范围
* @access public
* @return Model
* @return Query
*/
public static function useGlobalScope($use)
{
@@ -1697,13 +1786,14 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
/**
* 根据关联条件查询当前模型
* @access public
* @param string $relation 关联方法名
* @param mixed $where 查询条件(数组或者闭包)
* @param string $relation 关联方法名
* @param mixed $where 查询条件(数组或者闭包)
* @param mixed $fields 字段
* @return Relation|Query
*/
public static function hasWhere($relation, $where = [])
public static function hasWhere($relation, $where = [], $fields = null)
{
return (new static())->$relation()->hasWhere($where);
return (new static())->$relation()->hasWhere($where, $fields);
}
/**
@@ -1860,7 +1950,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
* @access public
* @param string $model 模型名
* @param string $foreignKey 关联外键
* @param string $localKey 关联主键
* @param string $localKey 当前模型主键
* @param array $alias 别名定义(已经废弃)
* @param string $joinType JOIN类型
* @return HasOne
@@ -1900,7 +1990,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
* @access public
* @param string $model 模型名
* @param string $foreignKey 关联外键
* @param string $localKey 关联主键
* @param string $localKey 当前模型主键
* @return HasMany
*/
public function hasMany($model, $foreignKey = '', $localKey = '')
@@ -1919,7 +2009,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
* @param string $through 中间模型名
* @param string $foreignKey 关联外键
* @param string $throughKey 关联外键
* @param string $localKey 关联主键
* @param string $localKey 当前模型主键
* @return HasManyThrough
*/
public function hasManyThrough($model, $through, $foreignKey = '', $throughKey = '', $localKey = '')
@@ -1969,7 +2059,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
$trace = debug_backtrace(false, 2);
$morph = Loader::parseName($trace[1]['function']);
}
$type = $type ?: Loader::parseName($this->name);
$type = $type ?: get_class($this);
if (is_array($morph)) {
list($morphType, $foreignKey) = $morph;
} else {
@@ -1995,7 +2085,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
$trace = debug_backtrace(false, 2);
$morph = Loader::parseName($trace[1]['function']);
}
$type = $type ?: Loader::parseName($this->name);
$type = $type ?: get_class($this);
if (is_array($morph)) {
list($morphType, $foreignKey) = $morph;
} else {
@@ -2033,7 +2123,6 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
public function __call($method, $args)
{
$query = $this->db(true, false);
if (method_exists($this, 'scope' . $method)) {
// 动态调用命名范围
$method = 'scope' . $method;
@@ -2049,7 +2138,6 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
{
$model = new static();
$query = $model->db();
if (method_exists($model, 'scope' . $method)) {
// 动态调用命名范围
$method = 'scope' . $method;