内核更新
This commit is contained in:
@@ -274,10 +274,6 @@ return [
|
|||||||
'datetime_format' => 'Y-m-d H:i:s',
|
'datetime_format' => 'Y-m-d H:i:s',
|
||||||
// 是否需要进行SQL性能分析
|
// 是否需要进行SQL性能分析
|
||||||
'sql_explain' => false,
|
'sql_explain' => false,
|
||||||
// Builder类
|
|
||||||
'builder' => '',
|
|
||||||
// Query类
|
|
||||||
'query' => '\\think\\db\\Query',
|
|
||||||
],
|
],
|
||||||
|
|
||||||
//分页配置
|
//分页配置
|
||||||
|
|||||||
@@ -495,15 +495,16 @@ if (!function_exists('redirect')) {
|
|||||||
* @param mixed $url 重定向地址 支持Url::build方法的地址
|
* @param mixed $url 重定向地址 支持Url::build方法的地址
|
||||||
* @param array|integer $params 额外参数
|
* @param array|integer $params 额外参数
|
||||||
* @param integer $code 状态码
|
* @param integer $code 状态码
|
||||||
|
* @param array $with 隐式传参
|
||||||
* @return \think\response\Redirect
|
* @return \think\response\Redirect
|
||||||
*/
|
*/
|
||||||
function redirect($url = [], $params = [], $code = 302)
|
function redirect($url = [], $params = [], $code = 302, $with = [])
|
||||||
{
|
{
|
||||||
if (is_integer($params)) {
|
if (is_integer($params)) {
|
||||||
$code = $params;
|
$code = $params;
|
||||||
$params = [];
|
$params = [];
|
||||||
}
|
}
|
||||||
return Response::create($url, 'redirect', $code)->params($params);
|
return Response::create($url, 'redirect', $code)->params($params)->with($with);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
}
|
}
|
||||||
// 全局作用域
|
// 全局作用域
|
||||||
if ($baseQuery && method_exists($this, 'base')) {
|
if ($baseQuery && method_exists($this, 'base')) {
|
||||||
call_user_func_array([$this, 'base'], [& self::$links[$model]]);
|
call_user_func_array([$this, 'base'], [ & self::$links[$model]]);
|
||||||
}
|
}
|
||||||
// 返回当前模型的数据库查询对象
|
// 返回当前模型的数据库查询对象
|
||||||
return self::$links[$model];
|
return self::$links[$model];
|
||||||
@@ -328,7 +328,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
} elseif (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), [
|
} elseif (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), [
|
||||||
'datetime',
|
'datetime',
|
||||||
'date',
|
'date',
|
||||||
'timestamp'
|
'timestamp',
|
||||||
])
|
])
|
||||||
) {
|
) {
|
||||||
$value = $this->formatDateTime($_SERVER['REQUEST_TIME'], $this->dateFormat);
|
$value = $this->formatDateTime($_SERVER['REQUEST_TIME'], $this->dateFormat);
|
||||||
@@ -350,7 +350,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
{
|
{
|
||||||
if (false !== strpos($format, '\\')) {
|
if (false !== strpos($format, '\\')) {
|
||||||
$time = new $format($time);
|
$time = new $format($time);
|
||||||
} elseif (!$timestamp) {
|
} elseif (!$timestamp && false !== $format) {
|
||||||
$time = date($format, $time);
|
$time = date($format, $time);
|
||||||
}
|
}
|
||||||
return $time;
|
return $time;
|
||||||
@@ -441,7 +441,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
if (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), [
|
if (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), [
|
||||||
'datetime',
|
'datetime',
|
||||||
'date',
|
'date',
|
||||||
'timestamp'
|
'timestamp',
|
||||||
])
|
])
|
||||||
) {
|
) {
|
||||||
$value = $this->formatDateTime(strtotime($value), $this->dateFormat);
|
$value = $this->formatDateTime(strtotime($value), $this->dateFormat);
|
||||||
@@ -1018,6 +1018,21 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置只读字段
|
||||||
|
* @access public
|
||||||
|
* @param mixed $field 只读字段
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function readonly($field)
|
||||||
|
{
|
||||||
|
if (is_string($field)) {
|
||||||
|
$field = explode(',', $field);
|
||||||
|
}
|
||||||
|
$this->readonly = $field;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否为更新数据
|
* 是否为更新数据
|
||||||
* @access public
|
* @access public
|
||||||
@@ -1219,7 +1234,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
if (isset(self::$event[$this->class][$event])) {
|
if (isset(self::$event[$this->class][$event])) {
|
||||||
foreach (self::$event[$this->class][$event] as $callback) {
|
foreach (self::$event[$this->class][$event] as $callback) {
|
||||||
if (is_callable($callback)) {
|
if (is_callable($callback)) {
|
||||||
$result = call_user_func_array($callback, [& $params]);
|
$result = call_user_func_array($callback, [ & $params]);
|
||||||
if (false === $result) {
|
if (false === $result) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1275,6 +1290,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
*/
|
*/
|
||||||
public static function get($data = null, $with = [], $cache = false)
|
public static function get($data = null, $with = [], $cache = false)
|
||||||
{
|
{
|
||||||
|
if (true === $with || is_int($with)) {
|
||||||
|
$cache = $with;
|
||||||
|
$with = [];
|
||||||
|
}
|
||||||
$query = static::parseQuery($data, $with, $cache);
|
$query = static::parseQuery($data, $with, $cache);
|
||||||
return $query->find($data);
|
return $query->find($data);
|
||||||
}
|
}
|
||||||
@@ -1290,6 +1309,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
*/
|
*/
|
||||||
public static function all($data = null, $with = [], $cache = false)
|
public static function all($data = null, $with = [], $cache = false)
|
||||||
{
|
{
|
||||||
|
if (true === $with || is_int($with)) {
|
||||||
|
$cache = $with;
|
||||||
|
$with = [];
|
||||||
|
}
|
||||||
$query = static::parseQuery($data, $with, $cache);
|
$query = static::parseQuery($data, $with, $cache);
|
||||||
return $query->select($data);
|
return $query->select($data);
|
||||||
}
|
}
|
||||||
@@ -1309,7 +1332,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
$result = $result->where($data);
|
$result = $result->where($data);
|
||||||
$data = null;
|
$data = null;
|
||||||
} elseif ($data instanceof \Closure) {
|
} elseif ($data instanceof \Closure) {
|
||||||
call_user_func_array($data, [& $result]);
|
call_user_func_array($data, [ & $result]);
|
||||||
$data = null;
|
$data = null;
|
||||||
} elseif ($data instanceof Query) {
|
} elseif ($data instanceof Query) {
|
||||||
$result = $data->with($with)->cache($cache);
|
$result = $data->with($with)->cache($cache);
|
||||||
@@ -1332,7 +1355,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
$query->where($data);
|
$query->where($data);
|
||||||
$data = null;
|
$data = null;
|
||||||
} 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 (is_null($data)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -153,7 +153,8 @@ class Url
|
|||||||
// 检测域名
|
// 检测域名
|
||||||
$domain = self::parseDomain($url, $domain);
|
$domain = self::parseDomain($url, $domain);
|
||||||
// URL组装
|
// URL组装
|
||||||
$url = $domain . (self::$root ?: Request::instance()->root()) . '/' . ltrim($url, '/');
|
$url = $domain . rtrim(self::$root ?: Request::instance()->root(), '/') . '/' . ltrim($url, '/');
|
||||||
|
|
||||||
self::$bindCheck = false;
|
self::$bindCheck = false;
|
||||||
return $url;
|
return $url;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -656,7 +656,7 @@ class Validate
|
|||||||
if (!in_array($rule, ['ipv4', 'ipv6'])) {
|
if (!in_array($rule, ['ipv4', 'ipv6'])) {
|
||||||
$rule = 'ipv4';
|
$rule = 'ipv4';
|
||||||
}
|
}
|
||||||
return $this->filter($value, FILTER_VALIDATE_IP, 'ipv6' == $rule ? FILTER_FLAG_IPV6 : FILTER_FLAG_IPV4);
|
return $this->filter($value, [FILTER_VALIDATE_IP, 'ipv6' == $rule ? FILTER_FLAG_IPV6 : FILTER_FLAG_IPV4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -872,6 +872,7 @@ class Validate
|
|||||||
list($rule, $param) = explode(',', $rule);
|
list($rule, $param) = explode(',', $rule);
|
||||||
} elseif (is_array($rule)) {
|
} elseif (is_array($rule)) {
|
||||||
$param = isset($rule[1]) ? $rule[1] : null;
|
$param = isset($rule[1]) ? $rule[1] : null;
|
||||||
|
$rule = $rule[0];
|
||||||
} else {
|
} else {
|
||||||
$param = null;
|
$param = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -250,7 +250,10 @@ abstract class Builder
|
|||||||
// 使用闭包查询
|
// 使用闭包查询
|
||||||
$query = new Query($this->connection);
|
$query = new Query($this->connection);
|
||||||
call_user_func_array($value, [ & $query]);
|
call_user_func_array($value, [ & $query]);
|
||||||
$str[] = ' ' . $key . ' ( ' . $this->buildWhere($query->getOptions('where'), $options) . ' )';
|
$whereClause = $this->buildWhere($query->getOptions('where'), $options);
|
||||||
|
if (!empty($whereClause)) {
|
||||||
|
$str[] = ' ' . $key . ' ( ' . $whereClause . ' )';
|
||||||
|
}
|
||||||
} elseif (strpos($field, '|')) {
|
} elseif (strpos($field, '|')) {
|
||||||
// 不同字段使用相同查询条件(OR)
|
// 不同字段使用相同查询条件(OR)
|
||||||
$array = explode('|', $field);
|
$array = explode('|', $field);
|
||||||
|
|||||||
@@ -108,6 +108,8 @@ abstract class Connection
|
|||||||
'builder' => '',
|
'builder' => '',
|
||||||
// Query类
|
// Query类
|
||||||
'query' => '\\think\\db\\Query',
|
'query' => '\\think\\db\\Query',
|
||||||
|
// 是否需要断线重连
|
||||||
|
'break_reconnect' => false,
|
||||||
];
|
];
|
||||||
|
|
||||||
// PDO连接参数
|
// PDO连接参数
|
||||||
@@ -391,6 +393,9 @@ 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)) {
|
||||||
|
return $this->close()->query($sql, $bind, $master, $pdo);
|
||||||
|
}
|
||||||
throw new PDOException($e, $this->config, $this->getLastsql());
|
throw new PDOException($e, $this->config, $this->getLastsql());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -446,6 +451,9 @@ 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)) {
|
||||||
|
return $this->close()->execute($sql, $bind);
|
||||||
|
}
|
||||||
throw new PDOException($e, $this->config, $this->getLastsql());
|
throw new PDOException($e, $this->config, $this->getLastsql());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -747,8 +755,9 @@ abstract class Connection
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭数据库
|
* 关闭数据库(或者重新连接)
|
||||||
* @access public
|
* @access public
|
||||||
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function close()
|
public function close()
|
||||||
{
|
{
|
||||||
@@ -756,6 +765,18 @@ abstract class Connection
|
|||||||
$this->linkWrite = null;
|
$this->linkWrite = null;
|
||||||
$this->linkRead = null;
|
$this->linkRead = null;
|
||||||
$this->links = [];
|
$this->links = [];
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否断线
|
||||||
|
* @access protected
|
||||||
|
* @param \PDOException $e 异常
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isBreak($e)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -419,11 +419,7 @@ class Query
|
|||||||
}
|
}
|
||||||
if (isset($cache)) {
|
if (isset($cache)) {
|
||||||
// 缓存数据
|
// 缓存数据
|
||||||
if (isset($cache['tag'])) {
|
$this->cacheData($key, $result, $cache);
|
||||||
Cache::tag($cache['tag'])->set($key, $result, $cache['expire']);
|
|
||||||
} else {
|
|
||||||
Cache::set($key, $result, $cache['expire']);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 清空查询条件
|
// 清空查询条件
|
||||||
@@ -491,11 +487,7 @@ class Query
|
|||||||
}
|
}
|
||||||
if (isset($cache) && isset($guid)) {
|
if (isset($cache) && isset($guid)) {
|
||||||
// 缓存数据
|
// 缓存数据
|
||||||
if (isset($cache['tag'])) {
|
$this->cacheData($guid, $result, $cache);
|
||||||
Cache::tag($cache['tag'])->set($guid, $result, $cache['expire']);
|
|
||||||
} else {
|
|
||||||
Cache::set($guid, $result, $cache['expire']);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 清空查询条件
|
// 清空查询条件
|
||||||
@@ -2070,11 +2062,18 @@ class Query
|
|||||||
// 执行操作
|
// 执行操作
|
||||||
$result = $this->execute($sql, $bind);
|
$result = $this->execute($sql, $bind);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$this->trigger('after_insert', $options);
|
|
||||||
}
|
|
||||||
if ($getLastInsID) {
|
|
||||||
$sequence = $sequence ?: (isset($options['sequence']) ? $options['sequence'] : null);
|
$sequence = $sequence ?: (isset($options['sequence']) ? $options['sequence'] : null);
|
||||||
return $this->getLastInsID($sequence);
|
$lastInsId = $this->getLastInsID($sequence);
|
||||||
|
if ($lastInsId) {
|
||||||
|
$pk = $this->getPk($options);
|
||||||
|
$data[$pk] = $lastInsId;
|
||||||
|
}
|
||||||
|
$options['data'] = $data;
|
||||||
|
$this->trigger('after_insert', $options);
|
||||||
|
|
||||||
|
if ($getLastInsID) {
|
||||||
|
return $lastInsId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
@@ -2157,8 +2156,8 @@ class Query
|
|||||||
$options = $this->parseExpress();
|
$options = $this->parseExpress();
|
||||||
$data = array_merge($options['data'], $data);
|
$data = array_merge($options['data'], $data);
|
||||||
$pk = $this->getPk($options);
|
$pk = $this->getPk($options);
|
||||||
if (isset($options['cache']) && is_string($options['cache'])) {
|
if (isset($options['cache']) && is_string($options['cache']['key'])) {
|
||||||
$key = $options['cache'];
|
$key = $options['cache']['key'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($options['where'])) {
|
if (empty($options['where'])) {
|
||||||
@@ -2187,9 +2186,10 @@ class Query
|
|||||||
} else {
|
} else {
|
||||||
$options['where']['AND'] = $where;
|
$options['where']['AND'] = $where;
|
||||||
}
|
}
|
||||||
} elseif (is_string($pk) && isset($options['where']['AND'][$pk]) && is_scalar($options['where']['AND'][$pk])) {
|
} elseif (!isset($key) && is_string($pk) && isset($options['where']['AND'][$pk])) {
|
||||||
$key = 'think:' . $options['table'] . '|' . $options['where']['AND'][$pk];
|
$key = $this->getCacheKey($options['where']['AND'][$pk], $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成UPDATE SQL语句
|
// 生成UPDATE SQL语句
|
||||||
$sql = $this->builder->update($data, $options);
|
$sql = $this->builder->update($data, $options);
|
||||||
// 获取参数绑定
|
// 获取参数绑定
|
||||||
@@ -2206,6 +2206,13 @@ class Query
|
|||||||
// 执行操作
|
// 执行操作
|
||||||
$result = '' == $sql ? 0 : $this->execute($sql, $bind);
|
$result = '' == $sql ? 0 : $this->execute($sql, $bind);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
|
if (isset($where[$pk])) {
|
||||||
|
$data[$pk] = $where[$pk];
|
||||||
|
} elseif (is_string($pk) && isset($key) && strpos($key, '|')) {
|
||||||
|
list($a, $val) = explode('|', $key);
|
||||||
|
$data[$pk] = $val;
|
||||||
|
}
|
||||||
|
$options['data'] = $data;
|
||||||
$this->trigger('after_update', $options);
|
$this->trigger('after_update', $options);
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
@@ -2278,6 +2285,8 @@ class Query
|
|||||||
// 获取实际执行的SQL语句
|
// 获取实际执行的SQL语句
|
||||||
return $this->connection->getRealSql($sql, $bind);
|
return $this->connection->getRealSql($sql, $bind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$options['data'] = $data;
|
||||||
if ($resultSet = $this->trigger('before_select', $options)) {
|
if ($resultSet = $this->trigger('before_select', $options)) {
|
||||||
} else {
|
} else {
|
||||||
// 执行查询操作
|
// 执行查询操作
|
||||||
@@ -2291,11 +2300,7 @@ class Query
|
|||||||
|
|
||||||
if (isset($cache)) {
|
if (isset($cache)) {
|
||||||
// 缓存数据集
|
// 缓存数据集
|
||||||
if (isset($cache['tag'])) {
|
$this->cacheData($key, $resultSet, $cache);
|
||||||
Cache::tag($cache['tag'])->set($key, $resultSet, $cache['expire']);
|
|
||||||
} else {
|
|
||||||
Cache::set($key, $resultSet, $cache['expire']);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2339,6 +2344,40 @@ class Query
|
|||||||
return $resultSet;
|
return $resultSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存数据
|
||||||
|
* @access public
|
||||||
|
* @param string $key 缓存标识
|
||||||
|
* @param mixed $data 缓存数据
|
||||||
|
* @param array $config 缓存参数
|
||||||
|
*/
|
||||||
|
protected function cacheData($key, $data, $config = [])
|
||||||
|
{
|
||||||
|
if (isset($config['tag'])) {
|
||||||
|
Cache::tag($config['tag'])->set($key, $data, $config['expire']);
|
||||||
|
} else {
|
||||||
|
Cache::set($key, $data, $config['expire']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成缓存标识
|
||||||
|
* @access public
|
||||||
|
* @param mixed $value 缓存数据
|
||||||
|
* @param array $options 缓存参数
|
||||||
|
*/
|
||||||
|
protected function getCacheKey($value, $options)
|
||||||
|
{
|
||||||
|
if (is_scalar($value)) {
|
||||||
|
$data = $value;
|
||||||
|
} elseif (is_array($value) && 'eq' == strtolower($value[0])) {
|
||||||
|
$data = $value[1];
|
||||||
|
}
|
||||||
|
if (isset($data)) {
|
||||||
|
return 'think:' . $options['table'] . '|' . $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查找单条记录
|
* 查找单条记录
|
||||||
* @access public
|
* @access public
|
||||||
@@ -2358,10 +2397,12 @@ class Query
|
|||||||
}
|
}
|
||||||
// 分析查询表达式
|
// 分析查询表达式
|
||||||
$options = $this->parseExpress();
|
$options = $this->parseExpress();
|
||||||
|
$pk = $this->getPk($options);
|
||||||
if (!is_null($data)) {
|
if (!is_null($data)) {
|
||||||
// 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])) {
|
||||||
|
$key = $this->getCacheKey($options['where']['AND'][$pk], $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
$options['limit'] = 1;
|
$options['limit'] = 1;
|
||||||
@@ -2371,12 +2412,12 @@ class Query
|
|||||||
$cache = $options['cache'];
|
$cache = $options['cache'];
|
||||||
if (true === $cache['key'] && !is_null($data) && !is_array($data)) {
|
if (true === $cache['key'] && !is_null($data) && !is_array($data)) {
|
||||||
$key = 'think:' . (is_array($options['table']) ? key($options['table']) : $options['table']) . '|' . $data;
|
$key = 'think:' . (is_array($options['table']) ? key($options['table']) : $options['table']) . '|' . $data;
|
||||||
} else {
|
} elseif (!isset($key)) {
|
||||||
$key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options));
|
$key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options));
|
||||||
}
|
}
|
||||||
$result = Cache::get($key);
|
$result = Cache::get($key);
|
||||||
}
|
}
|
||||||
if (!$result) {
|
if (false === $result) {
|
||||||
// 生成查询SQL
|
// 生成查询SQL
|
||||||
$sql = $this->builder->select($options);
|
$sql = $this->builder->select($options);
|
||||||
// 获取参数绑定
|
// 获取参数绑定
|
||||||
@@ -2385,56 +2426,61 @@ class Query
|
|||||||
// 获取实际执行的SQL语句
|
// 获取实际执行的SQL语句
|
||||||
return $this->connection->getRealSql($sql, $bind);
|
return $this->connection->getRealSql($sql, $bind);
|
||||||
}
|
}
|
||||||
|
if (is_string($pk)) {
|
||||||
|
if (!is_array($data)) {
|
||||||
|
if (isset($key) && strpos($key, '|')) {
|
||||||
|
list($a, $val) = explode('|', $key);
|
||||||
|
$item[$pk] = $val;
|
||||||
|
} else {
|
||||||
|
$item[$pk] = $data;
|
||||||
|
}
|
||||||
|
$data = $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$options['data'] = $data;
|
||||||
// 事件回调
|
// 事件回调
|
||||||
if ($result = $this->trigger('before_find', $options)) {
|
if ($result = $this->trigger('before_find', $options)) {
|
||||||
} else {
|
} else {
|
||||||
// 执行查询
|
// 执行查询
|
||||||
$result = $this->query($sql, $bind, $options['master'], $options['fetch_pdo']);
|
$resultSet = $this->query($sql, $bind, $options['master'], $options['fetch_pdo']);
|
||||||
|
|
||||||
if ($result instanceof \PDOStatement) {
|
if ($resultSet instanceof \PDOStatement) {
|
||||||
// 返回PDOStatement对象
|
// 返回PDOStatement对象
|
||||||
return $result;
|
return $resultSet;
|
||||||
}
|
}
|
||||||
|
$result = isset($resultSet[0]) ? $resultSet[0] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($cache)) {
|
if (isset($cache)) {
|
||||||
// 缓存数据
|
// 缓存数据
|
||||||
if (isset($cache['tag'])) {
|
$this->cacheData($key, $result, $cache);
|
||||||
Cache::tag($cache['tag'])->set($key, $result, $cache['expire']);
|
|
||||||
} else {
|
|
||||||
Cache::set($key, $result, $cache['expire']);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数据处理
|
// 数据处理
|
||||||
if (!empty($result[0])) {
|
if (!empty($result)) {
|
||||||
$data = $result[0];
|
|
||||||
if (!empty($this->model)) {
|
if (!empty($this->model)) {
|
||||||
// 返回模型对象
|
// 返回模型对象
|
||||||
$model = $this->model;
|
$model = $this->model;
|
||||||
$data = new $model($data);
|
$result = new $model($result);
|
||||||
$data->isUpdate(true, isset($options['where']['AND']) ? $options['where']['AND'] : null);
|
$result->isUpdate(true, isset($options['where']['AND']) ? $options['where']['AND'] : null);
|
||||||
// 关联查询
|
// 关联查询
|
||||||
if (!empty($options['relation'])) {
|
if (!empty($options['relation'])) {
|
||||||
$data->relationQuery($options['relation']);
|
$result->relationQuery($options['relation']);
|
||||||
}
|
}
|
||||||
// 预载入查询
|
// 预载入查询
|
||||||
if (!empty($options['with'])) {
|
if (!empty($options['with'])) {
|
||||||
$data->eagerlyResult($data, $options['with']);
|
$result->eagerlyResult($result, $options['with']);
|
||||||
}
|
}
|
||||||
// 关联统计
|
// 关联统计
|
||||||
if (!empty($options['with_count'])) {
|
if (!empty($options['with_count'])) {
|
||||||
$data->relationCount($data, $options['with_count']);
|
$result->relationCount($result, $options['with_count']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif (!empty($options['fail'])) {
|
} elseif (!empty($options['fail'])) {
|
||||||
$this->throwNotFound($options);
|
$this->throwNotFound($options);
|
||||||
} else {
|
|
||||||
$data = null;
|
|
||||||
}
|
}
|
||||||
return $data;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2565,8 +2611,9 @@ class Query
|
|||||||
{
|
{
|
||||||
// 分析查询表达式
|
// 分析查询表达式
|
||||||
$options = $this->parseExpress();
|
$options = $this->parseExpress();
|
||||||
if (isset($options['cache']) && is_string($options['cache'])) {
|
$pk = $this->getPk($options);
|
||||||
$key = $options['cache'];
|
if (isset($options['cache']) && is_string($options['cache']['key'])) {
|
||||||
|
$key = $options['cache']['key'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_null($data) && true !== $data) {
|
if (!is_null($data) && true !== $data) {
|
||||||
@@ -2576,6 +2623,8 @@ class Query
|
|||||||
}
|
}
|
||||||
// AR模式分析主键条件
|
// AR模式分析主键条件
|
||||||
$this->parsePkWhere($data, $options);
|
$this->parsePkWhere($data, $options);
|
||||||
|
} elseif (!isset($key) && is_string($pk) && isset($options['where']['AND'][$pk])) {
|
||||||
|
$key = $this->getCacheKey($options['where']['AND'][$pk], $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (true !== $data && empty($options['where'])) {
|
if (true !== $data && empty($options['where'])) {
|
||||||
@@ -2599,6 +2648,12 @@ class Query
|
|||||||
// 执行操作
|
// 执行操作
|
||||||
$result = $this->execute($sql, $bind);
|
$result = $this->execute($sql, $bind);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
|
if (!is_array($data) && is_string($pk) && isset($key) && strpos($key, '|')) {
|
||||||
|
list($a, $val) = explode('|', $key);
|
||||||
|
$item[$pk] = $val;
|
||||||
|
$data = $item;
|
||||||
|
}
|
||||||
|
$options['data'] = $data;
|
||||||
$this->trigger('after_delete', $options);
|
$this->trigger('after_delete', $options);
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
@@ -2711,15 +2766,15 @@ class Query
|
|||||||
* 触发事件
|
* 触发事件
|
||||||
* @access protected
|
* @access protected
|
||||||
* @param string $event 事件名
|
* @param string $event 事件名
|
||||||
* @param mixed $options 当前查询参数
|
* @param mixed $params 额外参数
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected function trigger($event, $options = [])
|
protected function trigger($event, $params = [])
|
||||||
{
|
{
|
||||||
$result = false;
|
$result = false;
|
||||||
if (isset(self::$event[$event])) {
|
if (isset(self::$event[$event])) {
|
||||||
$callback = self::$event[$event];
|
$callback = self::$event[$event];
|
||||||
$result = call_user_func_array($callback, [$options, $this]);
|
$result = call_user_func_array($callback, [$params, $this]);
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,4 +129,18 @@ 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class BelongsToMany extends Relation
|
|||||||
$localKey = $this->localKey;
|
$localKey = $this->localKey;
|
||||||
$middle = $this->middle;
|
$middle = $this->middle;
|
||||||
if ($closure) {
|
if ($closure) {
|
||||||
call_user_func_array($closure, [& $this->query]);
|
call_user_func_array($closure, [ & $this->query]);
|
||||||
}
|
}
|
||||||
// 关联查询
|
// 关联查询
|
||||||
$pk = $this->parent->getPk();
|
$pk = $this->parent->getPk();
|
||||||
@@ -174,8 +174,8 @@ class BelongsToMany extends Relation
|
|||||||
return $this->belongsToManyQuery($this->middle, $this->foreignKey, $this->localKey, [
|
return $this->belongsToManyQuery($this->middle, $this->foreignKey, $this->localKey, [
|
||||||
'pivot.' . $this->localKey => [
|
'pivot.' . $this->localKey => [
|
||||||
'exp',
|
'exp',
|
||||||
'=' . $this->parent->getTable() . '.' . $this->parent->getPk()
|
'=' . $this->parent->getTable() . '.' . $this->parent->getPk(),
|
||||||
]
|
],
|
||||||
])->fetchSql()->count();
|
])->fetchSql()->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +271,7 @@ class BelongsToMany extends Relation
|
|||||||
* @access public
|
* @access public
|
||||||
* @param mixed $data 数据 可以使用数组、关联模型对象 或者 关联对象的主键
|
* @param mixed $data 数据 可以使用数组、关联模型对象 或者 关联对象的主键
|
||||||
* @param array $pivot 中间表额外数据
|
* @param array $pivot 中间表额外数据
|
||||||
* @return int
|
* @return array|Pivot
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function attach($data, $pivot = [])
|
public function attach($data, $pivot = [])
|
||||||
@@ -301,7 +301,12 @@ class BelongsToMany extends Relation
|
|||||||
$ids = (array) $id;
|
$ids = (array) $id;
|
||||||
foreach ($ids as $id) {
|
foreach ($ids as $id) {
|
||||||
$pivot[$this->foreignKey] = $id;
|
$pivot[$this->foreignKey] = $id;
|
||||||
$result = $this->query->table($this->middle)->insert($pivot, true);
|
$this->query->table($this->middle)->insert($pivot, true);
|
||||||
|
$result[] = new Pivot($pivot, $this->middle);
|
||||||
|
}
|
||||||
|
if (count($result) == 1) {
|
||||||
|
// 返回中间表模型对象
|
||||||
|
$result = $result[0];
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class HasMany extends Relation
|
|||||||
public function getRelation($subRelation = '', $closure = null)
|
public function getRelation($subRelation = '', $closure = null)
|
||||||
{
|
{
|
||||||
if ($closure) {
|
if ($closure) {
|
||||||
call_user_func_array($closure, [& $this->query]);
|
call_user_func_array($closure, [ & $this->query]);
|
||||||
}
|
}
|
||||||
return $this->relation($subRelation)->select();
|
return $this->relation($subRelation)->select();
|
||||||
}
|
}
|
||||||
@@ -125,7 +125,7 @@ class HasMany extends Relation
|
|||||||
$count = 0;
|
$count = 0;
|
||||||
if (isset($result->$localKey)) {
|
if (isset($result->$localKey)) {
|
||||||
if ($closure) {
|
if ($closure) {
|
||||||
call_user_func_array($closure, [& $this->query]);
|
call_user_func_array($closure, [ & $this->query]);
|
||||||
}
|
}
|
||||||
$count = $this->query->where([$this->foreignKey => $result->$localKey])->count();
|
$count = $this->query->where([$this->foreignKey => $result->$localKey])->count();
|
||||||
}
|
}
|
||||||
@@ -141,14 +141,14 @@ class HasMany extends Relation
|
|||||||
public function getRelationCountQuery($closure)
|
public function getRelationCountQuery($closure)
|
||||||
{
|
{
|
||||||
if ($closure) {
|
if ($closure) {
|
||||||
call_user_func_array($closure, [& $this->query]);
|
call_user_func_array($closure, [ & $this->query]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->query->where([
|
return $this->query->where([
|
||||||
$this->foreignKey => [
|
$this->foreignKey => [
|
||||||
'exp',
|
'exp',
|
||||||
'=' . $this->parent->getTable() . '.' . $this->parent->getPk()
|
'=' . $this->parent->getTable() . '.' . $this->parent->getPk(),
|
||||||
]
|
],
|
||||||
])->fetchSql()->count();
|
])->fetchSql()->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ class HasMany extends Relation
|
|||||||
$foreignKey = $this->foreignKey;
|
$foreignKey = $this->foreignKey;
|
||||||
// 预载入关联查询 支持嵌套预载入
|
// 预载入关联查询 支持嵌套预载入
|
||||||
if ($closure) {
|
if ($closure) {
|
||||||
call_user_func_array($closure, [& $model]);
|
call_user_func_array($closure, [ & $model]);
|
||||||
}
|
}
|
||||||
$list = $model->where($where)->with($subRelation)->select();
|
$list = $model->where($where)->with($subRelation)->select();
|
||||||
|
|
||||||
@@ -217,13 +217,14 @@ class HasMany extends Relation
|
|||||||
* @param string $operator 比较操作符
|
* @param string $operator 比较操作符
|
||||||
* @param integer $count 个数
|
* @param integer $count 个数
|
||||||
* @param string $id 关联表的统计字段
|
* @param string $id 关联表的统计字段
|
||||||
|
* @param string $joinType JOIN类型
|
||||||
* @return Query
|
* @return Query
|
||||||
*/
|
*/
|
||||||
public function has($operator = '>=', $count = 1, $id = '*')
|
public function has($operator = '>=', $count = 1, $id = '*', $joinType = 'INNER')
|
||||||
{
|
{
|
||||||
$table = $this->query->getTable();
|
$table = $this->query->getTable();
|
||||||
return $this->parent->db()->alias('a')
|
return $this->parent->db()->alias('a')
|
||||||
->join($table . ' b', 'a.' . $this->localKey . '=b.' . $this->foreignKey, $this->joinType)
|
->join($table . ' b', 'a.' . $this->localKey . '=b.' . $this->foreignKey, $joinType)
|
||||||
->group('b.' . $this->foreignKey)
|
->group('b.' . $this->foreignKey)
|
||||||
->having('count(' . $id . ')' . $operator . $count);
|
->having('count(' . $id . ')' . $operator . $count);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,16 +131,17 @@ trait Jump
|
|||||||
* @param string $url 跳转的URL表达式
|
* @param string $url 跳转的URL表达式
|
||||||
* @param array|integer $params 其它URL参数
|
* @param array|integer $params 其它URL参数
|
||||||
* @param integer $code http code
|
* @param integer $code http code
|
||||||
|
* @param array $with 隐式传参
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function redirect($url, $params = [], $code = 302)
|
protected function redirect($url, $params = [], $code = 302, $with = [])
|
||||||
{
|
{
|
||||||
$response = new Redirect($url);
|
$response = new Redirect($url);
|
||||||
if (is_integer($params)) {
|
if (is_integer($params)) {
|
||||||
$code = $params;
|
$code = $params;
|
||||||
$params = [];
|
$params = [];
|
||||||
}
|
}
|
||||||
$response->code($code)->params($params);
|
$response->code($code)->params($params)->with($with);
|
||||||
throw new HttpResponseException($response);
|
throw new HttpResponseException($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ trait SoftDelete
|
|||||||
{
|
{
|
||||||
$model = new static();
|
$model = new static();
|
||||||
$field = $model->getDeleteTimeField(true);
|
$field = $model->getDeleteTimeField(true);
|
||||||
return $model->db(false)->where($field, 'exp', 'is not null');
|
return $model->db(false)->whereNotNull($field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -129,7 +129,7 @@ trait SoftDelete
|
|||||||
protected function base($query)
|
protected function base($query)
|
||||||
{
|
{
|
||||||
$field = $this->getDeleteTimeField(true);
|
$field = $this->getDeleteTimeField(true);
|
||||||
$query->where($field, 'null');
|
$query->whereNull($field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user