[升级]ThinkPHP框架升级到5.0.9

This commit is contained in:
Anyon 2017-05-23 17:15:01 +08:00
parent c3c5ca6201
commit 0e5d37e95c
24 changed files with 252 additions and 146 deletions

View File

@ -9,7 +9,7 @@
// | Author: liu21st <liu21st@gmail.com> // | Author: liu21st <liu21st@gmail.com>
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
define('THINK_VERSION', '5.0.8'); define('THINK_VERSION', '5.0.9');
define('THINK_START_TIME', microtime(true)); define('THINK_START_TIME', microtime(true));
define('THINK_START_MEM', memory_get_usage()); define('THINK_START_MEM', memory_get_usage());
define('EXT', '.php'); define('EXT', '.php');

View File

@ -192,7 +192,7 @@ if (!function_exists('db')) {
* @param bool $force 是否强制重新连接 * @param bool $force 是否强制重新连接
* @return \think\db\Query * @return \think\db\Query
*/ */
function db($name = '', $config = [], $force = true) function db($name = '', $config = [], $force = false)
{ {
return Db::connect($config, $force)->name($name); return Db::connect($config, $force)->name($name);
} }

View File

@ -176,7 +176,6 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
// 设置当前模型 确保查询返回模型对象 // 设置当前模型 确保查询返回模型对象
$queryClass = $this->query ?: $con->getConfig('query'); $queryClass = $this->query ?: $con->getConfig('query');
$query = new $queryClass($con, $this->class); $query = new $queryClass($con, $this->class);
$con->setQuery($query, $this->class);
// 设置当前数据表和模型名 // 设置当前数据表和模型名
if (!empty($this->table)) { if (!empty($this->table)) {
@ -659,14 +658,23 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
if (is_string($append)) { if (is_string($append)) {
$append = explode(',', $append); $append = explode(',', $append);
} }
$model = $this->getAttr($relation);
$relation = Loader::parseName($relation, 1, false);
// 获取关联数据
if (isset($this->relation[$relation])) {
$model = $this->relation[$relation];
} else {
$model = $this->getRelationData($this->$relation());
}
if ($model instanceof Model) { if ($model instanceof Model) {
foreach ($append as $key => $attr) { foreach ($append as $key => $attr) {
$key = is_numeric($key) ? $attr : $key; $key = is_numeric($key) ? $attr : $key;
if ($this->__isset($key)) { if (isset($this->data[$key])) {
throw new Exception('bind attr has exists:' . $key); throw new Exception('bind attr has exists:' . $key);
} else { } else {
$this->setAttr($key, $model->$attr); $this->data[$key] = $model->$attr;
} }
} }
} }
@ -779,7 +787,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
// 关联模型数据集 // 关联模型数据集
$arr = []; $arr = [];
foreach ($val as $k => $value) { foreach ($val as $k => $value) {
$arr[$k] = $this->subToArray($value, $visible, $hidden, $k); $arr[$k] = $this->subToArray($value, $visible, $hidden, $key);
} }
$item[$key] = $arr; $item[$key] = $arr;
} else { } else {
@ -928,18 +936,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} }
} elseif (isset($this->relation[$name])) { } elseif (isset($this->relation[$name])) {
$relation[$name] = $this->relation[$name]; $relation[$name] = $this->relation[$name];
} } elseif (isset($this->data[$name])) {
} $relation[$name] = $this->data[$name];
} unset($this->data[$name]);
// 检测字段
if (!empty($this->field)) {
if (true === $this->field) {
$this->field = $this->getQuery()->getTableInfo('', 'fields');
}
foreach ($this->data as $key => $val) {
if (!in_array($key, $this->field)) {
unset($this->data[$key]);
} }
} }
} }
@ -953,17 +952,20 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} }
$pk = $this->getPk(); $pk = $this->getPk();
if ($this->isUpdate) { if ($this->isUpdate) {
// 检测字段
$this->checkAllowField($this->data, array_merge($this->auto, $this->update));
// 自动更新 // 自动更新
$this->autoCompleteData($this->update); $this->autoCompleteData($this->update);
// 获取有更新的数据
$data = $this->getChangedData();
// 事件回调 // 事件回调
if (false === $this->trigger('before_update', $this)) { if (false === $this->trigger('before_update', $this)) {
return false; return false;
} }
// 获取有更新的数据
$data = $this->getChangedData();
if (empty($data) || (count($data) == 1 && is_string($pk) && isset($data[$pk]))) { if (empty($data) || (count($data) == 1 && is_string($pk) && isset($data[$pk]))) {
// 关联更新 // 关联更新
if (isset($relation)) { if (isset($relation)) {
@ -995,7 +997,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} }
// 模型更新 // 模型更新
$result = $this->db()->where($where)->update($data); $result = $this->getQuery()->where($where)->update($data);
// 关联更新 // 关联更新
if (isset($relation)) { if (isset($relation)) {
@ -1006,8 +1008,12 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
$this->trigger('after_update', $this); $this->trigger('after_update', $this);
} else { } else {
// 检测字段
$this->checkAllowField($this->data, array_merge($this->auto, $this->insert));
// 自动写入 // 自动写入
$this->autoCompleteData($this->insert); $this->autoCompleteData($this->insert);
// 自动写入创建时间和更新时间 // 自动写入创建时间和更新时间
if ($this->autoWriteTimestamp) { if ($this->autoWriteTimestamp) {
if ($this->createTime && !isset($this->data[$this->createTime])) { if ($this->createTime && !isset($this->data[$this->createTime])) {
@ -1022,11 +1028,11 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
return false; return false;
} }
$result = $this->db()->insert($this->data); $result = $this->getQuery()->insert($this->data);
// 获取自动增长主键 // 获取自动增长主键
if ($result && is_string($pk) && (!isset($this->data[$pk]) || '' == $this->data[$pk])) { if ($result && is_string($pk) && (!isset($this->data[$pk]) || '' == $this->data[$pk])) {
$insertId = $this->db()->getLastInsID($sequence); $insertId = $this->getQuery()->getLastInsID($sequence);
if ($insertId) { if ($insertId) {
$this->data[$pk] = $insertId; $this->data[$pk] = $insertId;
} }
@ -1055,6 +1061,24 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
return $result; return $result;
} }
protected function checkAllowField(&$data, $auto = [])
{
if (!empty($this->field)) {
if (true === $this->field) {
$this->field = $this->getQuery()->getTableInfo('', 'fields');
$field = $this->field;
} else {
$field = array_merge($this->field, $auto);
}
foreach ($data as $key => $val) {
if (!in_array($key, $field)) {
unset($data[$key]);
}
}
}
}
protected function autoRelationUpdate($relation) protected function autoRelationUpdate($relation)
{ {
foreach ($relation as $name => $val) { foreach ($relation as $name => $val) {
@ -1078,6 +1102,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
public function getChangedData() public function getChangedData()
{ {
$data = array_udiff_assoc($this->data, $this->origin, function ($a, $b) { $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; return is_object($a) || $a != $b ? 1 : 0;
}); });
@ -1114,7 +1141,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} }
$result = []; $result = [];
$db = $this->db(); $db = $this->getQuery();
$db->startTrans(); $db->startTrans();
try { try {
$pk = $this->getPk(); $pk = $this->getPk();
@ -1228,7 +1255,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} }
// 删除当前模型数据 // 删除当前模型数据
$result = $this->db()->where($where)->delete(); $result = $this->getQuery()->where($where)->delete();
// 关联删除 // 关联删除
if (!empty($this->relationWrite)) { if (!empty($this->relationWrite)) {
@ -1502,7 +1529,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} elseif ($data instanceof \Closure) { } elseif ($data instanceof \Closure) {
call_user_func_array($data, [ & $query]); call_user_func_array($data, [ & $query]);
$data = null; $data = null;
} elseif (is_null($data)) { } elseif (empty($data) && 0 !== $data) {
return 0; return 0;
} }
$resultSet = $query->select($data); $resultSet = $query->select($data);

View File

@ -273,6 +273,23 @@ abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, J
return $this->items->isEmpty(); return $this->items->isEmpty();
} }
/**
* 给每个元素执行个回调
*
* @param callable $callback
* @return $this
*/
public function each(callable $callback)
{
foreach ($this->items as $key => $item) {
if ($callback($item, $key) === false) {
break;
}
}
return $this;
}
/** /**
* Retrieve an external iterator * Retrieve an external iterator
* @return Traversable An instance of an object implementing <b>Iterator</b> or * @return Traversable An instance of an object implementing <b>Iterator</b> or
@ -349,6 +366,7 @@ abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, J
'total' => $total, 'total' => $total,
'per_page' => $this->listRows(), 'per_page' => $this->listRows(),
'current_page' => $this->currentPage(), 'current_page' => $this->currentPage(),
'last_page' => $this->lastPage,
'data' => $this->items->toArray(), 'data' => $this->items->toArray(),
]; ];
} }

View File

@ -97,9 +97,7 @@ class Request
'atom' => 'application/atom+xml', 'atom' => 'application/atom+xml',
'pdf' => 'application/pdf', 'pdf' => 'application/pdf',
'text' => 'text/plain', 'text' => 'text/plain',
'png' => 'image/png', 'image' => 'image/png,image/jpg,image/jpeg,image/pjpeg,image/gif,image/webp,image/*',
'jpg' => 'image/jpg,image/jpeg,image/pjpeg',
'gif' => 'image/gif',
'csv' => 'text/csv', 'csv' => 'text/csv',
'html' => 'text/html,application/xhtml+xml,*/*', 'html' => 'text/html,application/xhtml+xml,*/*',
]; ];
@ -1034,7 +1032,7 @@ class Request
$filter = []; $filter = [];
} else { } else {
$filter = $filter ?: $this->filter; $filter = $filter ?: $this->filter;
if (is_string($filter)) { if (is_string($filter) && false === strpos($filter, '/')) {
$filter = explode(',', $filter); $filter = explode(',', $filter);
} else { } else {
$filter = (array) $filter; $filter = (array) $filter;
@ -1060,7 +1058,7 @@ class Request
// 调用函数或者方法过滤 // 调用函数或者方法过滤
$value = call_user_func($filter, $value); $value = call_user_func($filter, $value);
} elseif (is_scalar($value)) { } elseif (is_scalar($value)) {
if (strpos($filter, '/')) { if (false !== strpos($filter, '/')) {
// 正则过滤 // 正则过滤
if (!preg_match($filter, $value)) { if (!preg_match($filter, $value)) {
// 匹配不成功返回默认值 // 匹配不成功返回默认值

View File

@ -19,7 +19,6 @@ use think\response\Xml as XmlResponse;
class Response class Response
{ {
// 原始数据 // 原始数据
protected $data; protected $data;
@ -50,12 +49,12 @@ class Response
public function __construct($data = '', $code = 200, array $header = [], $options = []) public function __construct($data = '', $code = 200, array $header = [], $options = [])
{ {
$this->data($data); $this->data($data);
$this->header = $header;
$this->code = $code;
if (!empty($options)) { if (!empty($options)) {
$this->options = array_merge($this->options, $options); $this->options = array_merge($this->options, $options);
} }
$this->contentType($this->contentType, $this->charset); $this->contentType($this->contentType, $this->charset);
$this->header = array_merge($this->header, $header);
$this->code = $code;
} }
/** /**

View File

@ -924,7 +924,7 @@ class Route
} else { } else {
$str = $key; $str = $key;
} }
if (is_string($str) && $str && 0 !== strpos(str_replace('|', '/', $url), $str)) { if (is_string($str) && $str && 0 !== stripos(str_replace('|', '/', $url), $str)) {
continue; continue;
} }
self::setOption($option); self::setOption($option);

View File

@ -297,7 +297,7 @@ class Url
} }
foreach ($pattern as $key => $val) { foreach ($pattern as $key => $val) {
if (isset($vars[$key])) { if (isset($vars[$key])) {
$url = str_replace(['[:' . $key . ']', '<' . $key . '?>', ':' . $key . '', '<' . $key . '>'], $vars[$key], $url); $url = str_replace(['[:' . $key . ']', '<' . $key . '?>', ':' . $key . '', '<' . $key . '>'], urlencode($vars[$key]), $url);
unset($vars[$key]); unset($vars[$key]);
$result = [$url, $domain, $suffix]; $result = [$url, $domain, $suffix];
} elseif (2 == $val) { } elseif (2 == $val) {

View File

@ -348,9 +348,14 @@ abstract class Builder
$whereStr = ''; $whereStr = '';
if (in_array($exp, ['=', '<>', '>', '>=', '<', '<='])) { if (in_array($exp, ['=', '<>', '>', '>=', '<', '<='])) {
// 比较运算 及 模糊匹配 // 比较运算
if ($value instanceof \Closure) {
$whereStr .= $key . ' ' . $exp . ' ' . $this->parseClosure($value);
} else {
$whereStr .= $key . ' ' . $exp . ' ' . $this->parseValue($value, $field); $whereStr .= $key . ' ' . $exp . ' ' . $this->parseValue($value, $field);
}
} elseif ('LIKE' == $exp || 'NOT LIKE' == $exp) { } elseif ('LIKE' == $exp || 'NOT LIKE' == $exp) {
// 模糊匹配
if (is_array($value)) { if (is_array($value)) {
foreach ($value as $item) { foreach ($value as $item) {
$array[] = $key . ' ' . $exp . ' ' . $this->parseValue($item, $field); $array[] = $key . ' ' . $exp . ' ' . $this->parseValue($item, $field);

View File

@ -56,8 +56,6 @@ abstract class Connection
protected $attrCase = PDO::CASE_LOWER; protected $attrCase = PDO::CASE_LOWER;
// 监听回调 // 监听回调
protected static $event = []; protected static $event = [];
// 查询对象
protected $query = [];
// 使用Builder类 // 使用Builder类
protected $builder; protected $builder;
// 数据库连接参数配置 // 数据库连接参数配置
@ -137,32 +135,14 @@ abstract class Connection
} }
/** /**
* 指定当前使用的查询对象 * 获取新的查询对象
* @access public * @access protected
* @param Query $query 查询对象
* @return $this
*/
public function setQuery($query, $model = 'db')
{
$this->query[$model] = $query;
return $this;
}
/**
* 创建指定模型的查询对象
* @access public
* @return Query * @return Query
*/ */
public function getQuery($model = 'db') protected function getQuery()
{ {
if (!isset($this->query[$model])) {
$class = $this->config['query']; $class = $this->config['query'];
return new $class($this);
$this->query[$model] = new $class($this, 'db' == $model ? '' : $model);
}
return $this->query[$model];
} }
/** /**
@ -402,10 +382,15 @@ abstract class Connection
// 返回结果集 // 返回结果集
return $this->getResult($pdo, $procedure); return $this->getResult($pdo, $procedure);
} catch (\PDOException $e) { } catch (\PDOException $e) {
if ($this->config['break_reconnect'] && $this->isBreak($e)) { if ($this->isBreak($e)) {
return $this->close()->query($sql, $bind, $master, $pdo); return $this->close()->query($sql, $bind, $master, $pdo);
} }
throw new PDOException($e, $this->config, $this->getLastsql()); throw new PDOException($e, $this->config, $this->getLastsql());
} catch (\ErrorException $e) {
if ($this->isBreak($e)) {
return $this->close()->query($sql, $bind, $master, $pdo);
}
throw $e;
} }
} }
@ -460,10 +445,15 @@ abstract class Connection
$this->numRows = $this->PDOStatement->rowCount(); $this->numRows = $this->PDOStatement->rowCount();
return $this->numRows; return $this->numRows;
} catch (\PDOException $e) { } catch (\PDOException $e) {
if ($this->config['break_reconnect'] && $this->isBreak($e)) { if ($this->isBreak($e)) {
return $this->close()->execute($sql, $bind); return $this->close()->execute($sql, $bind);
} }
throw new PDOException($e, $this->config, $this->getLastsql()); throw new PDOException($e, $this->config, $this->getLastsql());
} catch (\ErrorException $e) {
if ($this->isBreak($e)) {
return $this->close()->execute($sql, $bind);
}
throw $e;
} }
} }
@ -638,7 +628,7 @@ abstract class Connection
} }
++$this->transTimes; ++$this->transTimes;
try {
if (1 == $this->transTimes) { if (1 == $this->transTimes) {
$this->linkID->beginTransaction(); $this->linkID->beginTransaction();
} elseif ($this->transTimes > 1 && $this->supportSavepoint()) { } elseif ($this->transTimes > 1 && $this->supportSavepoint()) {
@ -646,6 +636,18 @@ abstract class Connection
$this->parseSavepoint('trans' . $this->transTimes) $this->parseSavepoint('trans' . $this->transTimes)
); );
} }
} catch (\PDOException $e) {
if ($this->isBreak($e)) {
return $this->close()->startTrans();
}
throw $e;
} catch (\ErrorException $e) {
if ($this->isBreak($e)) {
return $this->close()->startTrans();
}
throw $e;
}
} }
/** /**
@ -780,11 +782,35 @@ abstract class Connection
/** /**
* 是否断线 * 是否断线
* @access protected * @access protected
* @param \PDOException $e 异常 * @param \PDOException $e 异常对象
* @return bool * @return bool
*/ */
protected function isBreak($e) protected function isBreak($e)
{ {
if (!$this->config['break_reconnect']) {
return false;
}
$info = [
'server has gone away',
'no connection to the server',
'Lost connection',
'is dead or not enabled',
'Error while sending',
'decryption failed or bad record mac',
'server closed the connection unexpectedly',
'SSL connection has been closed unexpectedly',
'Error writing data to the connection',
'Resource deadlock avoided',
];
$error = $e->getMessage();
foreach ($info as $msg) {
if (false !== stripos($error, $msg)) {
return true;
}
}
return false; return false;
} }
@ -869,7 +895,6 @@ abstract class Connection
Debug::remark('queryEndTime', 'time'); Debug::remark('queryEndTime', 'time');
$runtime = Debug::getRangeTime('queryStartTime', 'queryEndTime'); $runtime = Debug::getRangeTime('queryStartTime', 'queryEndTime');
$sql = $sql ?: $this->getLastsql(); $sql = $sql ?: $this->getLastsql();
$log = $sql . ' [ RunTime:' . $runtime . 's ]';
$result = []; $result = [];
// SQL性能分析 // SQL性能分析
if ($this->config['sql_explain'] && 0 === stripos(trim($sql), 'select')) { if ($this->config['sql_explain'] && 0 === stripos(trim($sql), 'select')) {

View File

@ -401,7 +401,7 @@ class Query
if (empty($this->options['table'])) { if (empty($this->options['table'])) {
$this->options['table'] = $this->getTable(); $this->options['table'] = $this->getTable();
} }
$key = is_string($cache['key']) ? $cache['key'] : md5($field . serialize($this->options)); $key = is_string($cache['key']) ? $cache['key'] : md5($field . serialize($this->options) . serialize($this->bind));
$result = Cache::get($key); $result = Cache::get($key);
} }
if (false === $result) { if (false === $result) {
@ -444,7 +444,7 @@ class Query
if (empty($this->options['table'])) { if (empty($this->options['table'])) {
$this->options['table'] = $this->getTable(); $this->options['table'] = $this->getTable();
} }
$guid = is_string($cache['key']) ? $cache['key'] : md5($field . serialize($this->options)); $guid = is_string($cache['key']) ? $cache['key'] : md5($field . serialize($this->options) . serialize($this->bind));
$result = Cache::get($guid); $result = Cache::get($guid);
} }
if (false === $result) { if (false === $result) {
@ -596,7 +596,7 @@ class Query
} }
if ($lazyTime > 0) { if ($lazyTime > 0) {
// 延迟写入 // 延迟写入
$guid = md5($this->getTable() . '_' . $field . '_' . serialize($condition)); $guid = md5($this->getTable() . '_' . $field . '_' . serialize($condition) . serialize($this->bind));
$step = $this->lazyWrite('inc', $guid, $step, $lazyTime); $step = $this->lazyWrite('inc', $guid, $step, $lazyTime);
if (false === $step) { if (false === $step) {
// 清空查询条件 // 清空查询条件
@ -625,7 +625,7 @@ class Query
} }
if ($lazyTime > 0) { if ($lazyTime > 0) {
// 延迟写入 // 延迟写入
$guid = md5($this->getTable() . '_' . $field . '_' . serialize($condition)); $guid = md5($this->getTable() . '_' . $field . '_' . serialize($condition) . serialize($this->bind));
$step = $this->lazyWrite('dec', $guid, $step, $lazyTime); $step = $this->lazyWrite('dec', $guid, $step, $lazyTime);
if (false === $step) { if (false === $step) {
// 清空查询条件 // 清空查询条件
@ -1134,6 +1134,7 @@ class Query
if ($field) { if ($field) {
$this->options['soft_delete'] = [$field, $condition ?: ['null', '']]; $this->options['soft_delete'] = [$field, $condition ?: ['null', '']];
} }
return $this;
} }
/** /**
@ -1902,6 +1903,9 @@ class Query
$closure = $relation; $closure = $relation;
$relation = $key; $relation = $key;
$with[$key] = $key; $with[$key] = $key;
} elseif (is_array($relation)) {
$subRelation = $relation;
$relation = $key;
} elseif (is_string($relation) && strpos($relation, '.')) { } elseif (is_string($relation) && strpos($relation, '.')) {
$with[$key] = $relation; $with[$key] = $relation;
list($relation, $subRelation) = explode('.', $relation, 2); list($relation, $subRelation) = explode('.', $relation, 2);
@ -2205,7 +2209,7 @@ class Query
$options['where']['AND'] = $where; $options['where']['AND'] = $where;
} }
} elseif (!isset($key) && is_string($pk) && isset($options['where']['AND'][$pk])) { } elseif (!isset($key) && is_string($pk) && isset($options['where']['AND'][$pk])) {
$key = $this->getCacheKey($options['where']['AND'][$pk], $options); $key = $this->getCacheKey($options['where']['AND'][$pk], $options, $this->bind);
} }
// 生成UPDATE SQL语句 // 生成UPDATE SQL语句
@ -2293,7 +2297,7 @@ class Query
// 判断查询缓存 // 判断查询缓存
$cache = $options['cache']; $cache = $options['cache'];
unset($options['cache']); unset($options['cache']);
$key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options)); $key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options) . serialize($this->bind));
$resultSet = Cache::get($key); $resultSet = Cache::get($key);
} }
if (!$resultSet) { if (!$resultSet) {
@ -2385,8 +2389,9 @@ class Query
* @access public * @access public
* @param mixed $value 缓存数据 * @param mixed $value 缓存数据
* @param array $options 缓存参数 * @param array $options 缓存参数
* @param array $bind 绑定参数
*/ */
protected function getCacheKey($value, $options) protected function getCacheKey($value, $options, $bind = [])
{ {
if (is_scalar($value)) { if (is_scalar($value)) {
$data = $value; $data = $value;
@ -2394,9 +2399,9 @@ class Query
$data = $value[1]; $data = $value[1];
} }
if (isset($data)) { if (isset($data)) {
return 'think:' . $options['table'] . '|' . $data; return 'think:' . (is_array($options['table']) ? key($options['table']) : $options['table']) . '|' . $data;
} else { } else {
return md5(serialize($options)); return md5(serialize($options) . serialize($bind));
} }
} }
@ -2424,7 +2429,7 @@ class Query
// AR模式分析主键条件 // AR模式分析主键条件
$this->parsePkWhere($data, $options); $this->parsePkWhere($data, $options);
} elseif (!empty($options['cache']) && true === $options['cache']['key'] && is_string($pk) && isset($options['where']['AND'][$pk])) { } elseif (!empty($options['cache']) && true === $options['cache']['key'] && is_string($pk) && isset($options['where']['AND'][$pk])) {
$key = $this->getCacheKey($options['where']['AND'][$pk], $options); $key = $this->getCacheKey($options['where']['AND'][$pk], $options, $this->bind);
} }
$options['limit'] = 1; $options['limit'] = 1;
@ -2437,7 +2442,7 @@ class Query
} elseif (is_string($cache['key'])) { } elseif (is_string($cache['key'])) {
$key = $cache['key']; $key = $cache['key'];
} elseif (!isset($key)) { } elseif (!isset($key)) {
$key = md5(serialize($options)); $key = md5(serialize($options) . serialize($this->bind));
} }
$result = Cache::get($key); $result = Cache::get($key);
} }
@ -2648,7 +2653,7 @@ class Query
// AR模式分析主键条件 // AR模式分析主键条件
$this->parsePkWhere($data, $options); $this->parsePkWhere($data, $options);
} elseif (!isset($key) && is_string($pk) && isset($options['where']['AND'][$pk])) { } elseif (!isset($key) && is_string($pk) && isset($options['where']['AND'][$pk])) {
$key = $this->getCacheKey($options['where']['AND'][$pk], $options); $key = $this->getCacheKey($options['where']['AND'][$pk], $options, $this->bind);
} }
if (true !== $data && empty($options['where'])) { if (true !== $data && empty($options['where'])) {

View File

@ -51,7 +51,7 @@ class Mysql extends Connection
*/ */
public function getFields($tableName) public function getFields($tableName)
{ {
$this->initConnect(true); $this->initConnect(false);
list($tableName) = explode(' ', $tableName); list($tableName) = explode(' ', $tableName);
if (false === strpos($tableName, '`')) { if (false === strpos($tableName, '`')) {
if (strpos($tableName, '.')) { if (strpos($tableName, '.')) {
@ -91,7 +91,7 @@ class Mysql extends Connection
*/ */
public function getTables($dbName = '') public function getTables($dbName = '')
{ {
$this->initConnect(true); $this->initConnect(false);
$sql = !empty($dbName) ? 'SHOW TABLES FROM ' . $dbName : 'SHOW TABLES '; $sql = !empty($dbName) ? 'SHOW TABLES FROM ' . $dbName : 'SHOW TABLES ';
// 调试开始 // 调试开始
$this->debug(true); $this->debug(true);
@ -130,17 +130,4 @@ class Mysql extends Connection
return true; return true;
} }
/**
* 是否断线
* @access protected
* @param \PDOException $e 异常对象
* @return bool
*/
protected function isBreak($e)
{
if (false !== stripos($e->getMessage(), 'server has gone away')) {
return true;
}
return false;
}
} }

View File

@ -44,7 +44,7 @@ class Pgsql extends Connection
*/ */
public function getFields($tableName) public function getFields($tableName)
{ {
$this->initConnect(true); $this->initConnect(false);
list($tableName) = explode(' ', $tableName); list($tableName) = explode(' ', $tableName);
$sql = 'select fields_name as "field",fields_type as "type",fields_not_null as "null",fields_key_name as "key",fields_default as "default",fields_default as "extra" from table_msg(\'' . $tableName . '\');'; $sql = 'select fields_name as "field",fields_type as "type",fields_not_null as "null",fields_key_name as "key",fields_default as "default",fields_default as "extra" from table_msg(\'' . $tableName . '\');';
// 调试开始 // 调试开始
@ -78,7 +78,7 @@ class Pgsql extends Connection
*/ */
public function getTables($dbName = '') public function getTables($dbName = '')
{ {
$this->initConnect(true); $this->initConnect(false);
$sql = "select tablename as Tables_in_test from pg_tables where schemaname ='public'"; $sql = "select tablename as Tables_in_test from pg_tables where schemaname ='public'";
// 调试开始 // 调试开始
$this->debug(true); $this->debug(true);

View File

@ -42,7 +42,7 @@ class Sqlite extends Connection
*/ */
public function getFields($tableName) public function getFields($tableName)
{ {
$this->initConnect(true); $this->initConnect(false);
list($tableName) = explode(' ', $tableName); list($tableName) = explode(' ', $tableName);
$sql = 'PRAGMA table_info( ' . $tableName . ' )'; $sql = 'PRAGMA table_info( ' . $tableName . ' )';
// 调试开始 // 调试开始
@ -76,7 +76,7 @@ class Sqlite extends Connection
*/ */
public function getTables($dbName = '') public function getTables($dbName = '')
{ {
$this->initConnect(true); $this->initConnect(false);
$sql = "SELECT name FROM sqlite_master WHERE type='table' " $sql = "SELECT name FROM sqlite_master WHERE type='table' "
. "UNION ALL SELECT name FROM sqlite_temp_master " . "UNION ALL SELECT name FROM sqlite_temp_master "
. "WHERE type='table' ORDER BY name"; . "WHERE type='table' ORDER BY name";

View File

@ -49,7 +49,7 @@ class Sqlsrv extends Connection
*/ */
public function getFields($tableName) public function getFields($tableName)
{ {
$this->initConnect(true); $this->initConnect(false);
list($tableName) = explode(' ', $tableName); list($tableName) = explode(' ', $tableName);
$sql = "SELECT column_name, data_type, column_default, is_nullable $sql = "SELECT column_name, data_type, column_default, is_nullable
FROM information_schema.tables AS t FROM information_schema.tables AS t
@ -99,7 +99,7 @@ class Sqlsrv extends Connection
*/ */
public function getTables($dbName = '') public function getTables($dbName = '')
{ {
$this->initConnect(true); $this->initConnect(false);
$sql = "SELECT TABLE_NAME $sql = "SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' WHERE TABLE_TYPE = 'BASE TABLE'

View File

@ -76,7 +76,7 @@ class File
{ {
//检测日志文件大小,超过配置大小则备份日志文件重新生成 //检测日志文件大小,超过配置大小则备份日志文件重新生成
if (is_file($destination) && floor($this->config['file_size']) <= filesize($destination)) { if (is_file($destination) && floor($this->config['file_size']) <= filesize($destination)) {
rename($destination, dirname($destination) . DS . $_SERVER['REQUEST_TIME'] . '-' . basename($destination)); rename($destination, dirname($destination) . DS . time() . '-' . basename($destination));
$this->writed[$destination] = false; $this->writed[$destination] = false;
} }

View File

@ -16,6 +16,20 @@ use think\Model;
class Collection extends BaseCollection class Collection extends BaseCollection
{ {
/**
* 返回数组中指定的一列
* @param string $column_key
* @param string|null $index_key
* @return array
*/
public function column($column_key, $index_key = null)
{
if (function_exists('array_column')) {
return array_column($this->toArray(), $column_key, $index_key);
}
return parent::column($column_key, $index_key);
}
/** /**
* 延迟预载入关联查询 * 延迟预载入关联查询
* @access public * @access public

View File

@ -77,6 +77,32 @@ abstract class Relation
return (new $this->model)->toCollection($resultSet); return (new $this->model)->toCollection($resultSet);
} }
protected function getQueryFields($model)
{
$fields = $this->query->getOptions('field');
return $this->getRelationQueryFields($fields, $model);
}
protected function getRelationQueryFields($fields, $model)
{
if ($fields) {
if (is_string($fields)) {
$fields = explode(',', $fields);
}
foreach ($fields as &$field) {
if (false === strpos($field, '.')) {
$field = $model . '.' . $field;
}
}
} else {
$fields = $model . '.*';
}
return $fields;
}
/** /**
* 执行基础查询(仅执行一次) * 执行基础查询(仅执行一次)
* @access protected * @access protected

View File

@ -376,7 +376,9 @@ class BelongsToMany extends Relation
// 关联查询封装 // 关联查询封装
$tableName = $this->query->getTable(); $tableName = $this->query->getTable();
$table = $this->pivot->getTable(); $table = $this->pivot->getTable();
$query = $this->query->field($tableName . '.*') $fields = $this->getQueryFields($tableName);
$query = $this->query->field($fields)
->field(true, false, $table, 'pivot', 'pivot__'); ->field(true, false, $table, 'pivot', 'pivot__');
if (empty($this->baseQuery)) { if (empty($this->baseQuery)) {

View File

@ -79,7 +79,7 @@
<html> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title><?php echo lang('System Error'); ?></title> <title><?php echo \think\Lang::get('System Error'); ?></title>
<meta name="robots" content="noindex,nofollow" /> <meta name="robots" content="noindex,nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<style> <style>

2
vendor/autoload.php vendored
View File

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php'; require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit4885b8f51026b3a984c69470cba091c6::getLoader(); return ComposerAutoloaderInit7d452dbe9081dacf18dce50bfc2b7965::getLoader();

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer // autoload_real.php @generated by Composer
class ComposerAutoloaderInit4885b8f51026b3a984c69470cba091c6 class ComposerAutoloaderInit7d452dbe9081dacf18dce50bfc2b7965
{ {
private static $loader; private static $loader;
@ -19,15 +19,15 @@ class ComposerAutoloaderInit4885b8f51026b3a984c69470cba091c6
return self::$loader; return self::$loader;
} }
spl_autoload_register(array('ComposerAutoloaderInit4885b8f51026b3a984c69470cba091c6', 'loadClassLoader'), true, true); spl_autoload_register(array('ComposerAutoloaderInit7d452dbe9081dacf18dce50bfc2b7965', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(); self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit4885b8f51026b3a984c69470cba091c6', 'loadClassLoader')); spl_autoload_unregister(array('ComposerAutoloaderInit7d452dbe9081dacf18dce50bfc2b7965', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION'); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
if ($useStaticLoader) { if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php'; require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit4885b8f51026b3a984c69470cba091c6::getInitializer($loader)); call_user_func(\Composer\Autoload\ComposerStaticInit7d452dbe9081dacf18dce50bfc2b7965::getInitializer($loader));
} else { } else {
$map = require __DIR__ . '/autoload_namespaces.php'; $map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) { foreach ($map as $namespace => $path) {
@ -48,19 +48,19 @@ class ComposerAutoloaderInit4885b8f51026b3a984c69470cba091c6
$loader->register(true); $loader->register(true);
if ($useStaticLoader) { if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit4885b8f51026b3a984c69470cba091c6::$files; $includeFiles = Composer\Autoload\ComposerStaticInit7d452dbe9081dacf18dce50bfc2b7965::$files;
} else { } else {
$includeFiles = require __DIR__ . '/autoload_files.php'; $includeFiles = require __DIR__ . '/autoload_files.php';
} }
foreach ($includeFiles as $fileIdentifier => $file) { foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire4885b8f51026b3a984c69470cba091c6($fileIdentifier, $file); composerRequire7d452dbe9081dacf18dce50bfc2b7965($fileIdentifier, $file);
} }
return $loader; return $loader;
} }
} }
function composerRequire4885b8f51026b3a984c69470cba091c6($fileIdentifier, $file) function composerRequire7d452dbe9081dacf18dce50bfc2b7965($fileIdentifier, $file)
{ {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file; require $file;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload; namespace Composer\Autoload;
class ComposerStaticInit4885b8f51026b3a984c69470cba091c6 class ComposerStaticInit7d452dbe9081dacf18dce50bfc2b7965
{ {
public static $files = array ( public static $files = array (
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php', '9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
@ -383,9 +383,9 @@ class ComposerStaticInit4885b8f51026b3a984c69470cba091c6
public static function getInitializer(ClassLoader $loader) public static function getInitializer(ClassLoader $loader)
{ {
return \Closure::bind(function () use ($loader) { return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit4885b8f51026b3a984c69470cba091c6::$prefixLengthsPsr4; $loader->prefixLengthsPsr4 = ComposerStaticInit7d452dbe9081dacf18dce50bfc2b7965::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit4885b8f51026b3a984c69470cba091c6::$prefixDirsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInit7d452dbe9081dacf18dce50bfc2b7965::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit4885b8f51026b3a984c69470cba091c6::$classMap; $loader->classMap = ComposerStaticInit7d452dbe9081dacf18dce50bfc2b7965::$classMap;
}, null, ClassLoader::class); }, null, ClassLoader::class);
} }

View File

@ -169,17 +169,17 @@
}, },
{ {
"name": "topthink/framework", "name": "topthink/framework",
"version": "v5.0.8", "version": "v5.0.9",
"version_normalized": "5.0.8.0", "version_normalized": "5.0.9.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/top-think/framework.git", "url": "https://github.com/top-think/framework.git",
"reference": "02f8e8a9099c534d1b2c38385fcf1fa5404694d4" "reference": "24ae4b9042bf9acfd041eb34602b14eb8669bc3f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://files.phpcomposer.com/files/top-think/framework/02f8e8a9099c534d1b2c38385fcf1fa5404694d4.zip", "url": "https://files.phpcomposer.com/files/top-think/framework/24ae4b9042bf9acfd041eb34602b14eb8669bc3f.zip",
"reference": "02f8e8a9099c534d1b2c38385fcf1fa5404694d4", "reference": "24ae4b9042bf9acfd041eb34602b14eb8669bc3f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -194,7 +194,7 @@
"phpunit/phpunit": "4.8.*", "phpunit/phpunit": "4.8.*",
"sebastian/phpcpd": "2.*" "sebastian/phpcpd": "2.*"
}, },
"time": "2017-04-28 09:33:15", "time": "2017-05-20 10:43:04",
"type": "think-framework", "type": "think-framework",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {