fix(vendor): 修复依赖升级导致的不兼容问题

This commit is contained in:
2025-12-08 14:03:47 +08:00
parent 0a9eadcdd0
commit 951836083e
50 changed files with 660 additions and 1010 deletions

View File

@@ -167,7 +167,7 @@ class Captcha
* @param bool $api * @param bool $api
* @return Response * @return Response
*/ */
public function create(string $config = null, bool $api = false): Response public function create(string $config = null, bool $api = false)
{ {
$this->configure($config); $this->configure($config);
@@ -233,6 +233,14 @@ class Captcha
$content = ob_get_clean(); $content = ob_get_clean();
imagedestroy($this->im); imagedestroy($this->im);
// api调用
if ($api) {
return [
'code' => implode('', $text),
'img' => 'data:image/png;base64,' . chunk_split(base64_encode($content))
];
}
return response($content, 200, ['Content-Length' => strlen($content)])->contentType('image/png'); return response($content, 200, ['Content-Length' => strlen($content)])->contentType('image/png');
} }

View File

@@ -24,12 +24,6 @@ use Traversable;
/** /**
* 数据集管理类 * 数据集管理类
*
* @template TKey of array-key
* @template-covariant TValue
*
* @implements ArrayAccess<TKey, TValue>
* @implements IteratorAggregate<TKey, TValue>
*/ */
class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable, Arrayable, Jsonable class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable, Arrayable, Jsonable
{ {
@@ -39,19 +33,11 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
*/ */
protected $items = []; protected $items = [];
/**
* 构造函数
* @param iterable<TKey, TValue>|Collection<TKey, TValue> $items 数据
*/
public function __construct($items = []) public function __construct($items = [])
{ {
$this->items = $this->convertToArray($items); $this->items = $this->convertToArray($items);
} }
/**
* @param iterable<TKey, TValue>|Collection<TKey, TValue> $items
* @return static<TKey, TValue>
*/
public static function make($items = []) public static function make($items = [])
{ {
return new static($items); return new static($items);
@@ -59,6 +45,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 是否为空 * 是否为空
* @access public
* @return bool * @return bool
*/ */
public function isEmpty(): bool public function isEmpty(): bool
@@ -73,9 +60,6 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
}, $this->items); }, $this->items);
} }
/**
* @return array<TKey, TValue>
*/
public function all(): array public function all(): array
{ {
return $this->items; return $this->items;
@@ -84,6 +68,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 合并数组 * 合并数组
* *
* @access public
* @param mixed $items 数据 * @param mixed $items 数据
* @return static * @return static
*/ */
@@ -95,11 +80,12 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 按指定键整理数据 * 按指定键整理数据
* *
* @access public
* @param mixed $items 数据 * @param mixed $items 数据
* @param string|null $indexKey 键名 * @param string $indexKey 键名
* @return array * @return array
*/ */
public function dictionary($items = null, ?string &$indexKey = null) public function dictionary($items = null, string &$indexKey = null)
{ {
if ($items instanceof self) { if ($items instanceof self) {
$items = $items->all(); $items = $items->all();
@@ -121,11 +107,12 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 比较数组,返回差集 * 比较数组,返回差集
* *
* @access public
* @param mixed $items 数据 * @param mixed $items 数据
* @param string|null $indexKey 指定比较的键名 * @param string $indexKey 指定比较的键名
* @return static<TKey, TValue> * @return static
*/ */
public function diff($items, ?string $indexKey = null) public function diff($items, string $indexKey = null)
{ {
if ($this->isEmpty() || is_scalar($this->items[0])) { if ($this->isEmpty() || is_scalar($this->items[0])) {
return new static(array_diff($this->items, $this->convertToArray($items))); return new static(array_diff($this->items, $this->convertToArray($items)));
@@ -148,11 +135,12 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 比较数组,返回交集 * 比较数组,返回交集
* *
* @access public
* @param mixed $items 数据 * @param mixed $items 数据
* @param string|null $indexKey 指定比较的键名 * @param string $indexKey 指定比较的键名
* @return static<TKey, TValue> * @return static
*/ */
public function intersect($items, ?string $indexKey = null) public function intersect($items, string $indexKey = null)
{ {
if ($this->isEmpty() || is_scalar($this->items[0])) { if ($this->isEmpty() || is_scalar($this->items[0])) {
return new static(array_intersect($this->items, $this->convertToArray($items))); return new static(array_intersect($this->items, $this->convertToArray($items)));
@@ -175,7 +163,8 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 交换数组中的键和值 * 交换数组中的键和值
* *
* @return static<TValue, TKey> * @access public
* @return static
*/ */
public function flip() public function flip()
{ {
@@ -185,7 +174,8 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 返回数组中所有的键名 * 返回数组中所有的键名
* *
* @return static<TKey, TValue> * @access public
* @return static
*/ */
public function keys() public function keys()
{ {
@@ -194,7 +184,8 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 返回数组中所有的值组成的新 Collection 实例 * 返回数组中所有的值组成的新 Collection 实例
* @return static<int, TValue> * @access public
* @return static
*/ */
public function values() public function values()
{ {
@@ -204,7 +195,8 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 删除数组的最后一个元素(出栈) * 删除数组的最后一个元素(出栈)
* *
* @return TValue * @access public
* @return mixed
*/ */
public function pop() public function pop()
{ {
@@ -214,6 +206,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 通过使用用户自定义函数,以字符串返回数组 * 通过使用用户自定义函数,以字符串返回数组
* *
* @access public
* @param callable $callback 调用方法 * @param callable $callback 调用方法
* @param mixed $initial * @param mixed $initial
* @return mixed * @return mixed
@@ -226,7 +219,8 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 以相反的顺序返回数组。 * 以相反的顺序返回数组。
* *
* @return static<TKey, TValue> * @access public
* @return static
*/ */
public function reverse() public function reverse()
{ {
@@ -236,7 +230,8 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 删除数组中首个元素,并返回被删除元素的值 * 删除数组中首个元素,并返回被删除元素的值
* *
* @return TValue * @access public
* @return mixed
*/ */
public function shift() public function shift()
{ {
@@ -245,12 +240,12 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 在数组结尾插入一个元素 * 在数组结尾插入一个元素
* * @access public
* @param mixed $value 元素 * @param mixed $value 元素
* @param string|null $key KEY * @param string $key KEY
* @return $this * @return $this
*/ */
public function push($value, ?string $key = null) public function push($value, string $key = null)
{ {
if (is_null($key)) { if (is_null($key)) {
$this->items[] = $value; $this->items[] = $value;
@@ -264,6 +259,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 把一个数组分割为新的数组块. * 把一个数组分割为新的数组块.
* *
* @access public
* @param int $size 块大小 * @param int $size 块大小
* @param bool $preserveKeys * @param bool $preserveKeys
* @return static * @return static
@@ -281,12 +277,12 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 在数组开头插入一个元素 * 在数组开头插入一个元素
* * @access public
* @param mixed $value 元素 * @param mixed $value 元素
* @param string|null $key KEY * @param string $key KEY
* @return $this * @return $this
*/ */
public function unshift($value, ?string $key = null) public function unshift($value, string $key = null)
{ {
if (is_null($key)) { if (is_null($key)) {
array_unshift($this->items, $value); array_unshift($this->items, $value);
@@ -300,7 +296,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 给每个元素执行个回调 * 给每个元素执行个回调
* *
* * @access public
* @param callable $callback 回调 * @param callable $callback 回调
* @return $this * @return $this
*/ */
@@ -321,9 +317,9 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 用回调函数处理数组中的元素 * 用回调函数处理数组中的元素
* * @access public
* @param callable|null $callback 回调 * @param callable|null $callback 回调
* @return static<TKey, TValue> * @return static
*/ */
public function map(callable $callback) public function map(callable $callback)
{ {
@@ -332,11 +328,11 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 用回调函数过滤数组中的元素 * 用回调函数过滤数组中的元素
* * @access public
* @param callable|null $callback 回调 * @param callable|null $callback 回调
* @return static<TKey, TValue> * @return static
*/ */
public function filter(?callable $callback = null) public function filter(callable $callback = null)
{ {
if ($callback) { if ($callback) {
return new static(array_filter($this->items, $callback)); return new static(array_filter($this->items, $callback));
@@ -347,11 +343,11 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 根据字段条件过滤数组中的元素 * 根据字段条件过滤数组中的元素
* * @access public
* @param string $field 字段名 * @param string $field 字段名
* @param mixed $operator 操作符 * @param mixed $operator 操作符
* @param mixed $value 数据 * @param mixed $value 数据
* @return static<TKey, TValue> * @return static
*/ */
public function where(string $field, $operator, $value = null) public function where(string $field, $operator, $value = null)
{ {
@@ -409,10 +405,10 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* LIKE过滤 * LIKE过滤
* * @access public
* @param string $field 字段名 * @param string $field 字段名
* @param string $value 数据 * @param string $value 数据
* @return static<TKey, TValue> * @return static
*/ */
public function whereLike(string $field, string $value) public function whereLike(string $field, string $value)
{ {
@@ -421,10 +417,10 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* NOT LIKE过滤 * NOT LIKE过滤
* * @access public
* @param string $field 字段名 * @param string $field 字段名
* @param string $value 数据 * @param string $value 数据
* @return static<TKey, TValue> * @return static
*/ */
public function whereNotLike(string $field, string $value) public function whereNotLike(string $field, string $value)
{ {
@@ -433,10 +429,10 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* IN过滤 * IN过滤
* * @access public
* @param string $field 字段名 * @param string $field 字段名
* @param array $value 数据 * @param array $value 数据
* @return static<TKey, TValue> * @return static
*/ */
public function whereIn(string $field, array $value) public function whereIn(string $field, array $value)
{ {
@@ -445,10 +441,10 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* NOT IN过滤 * NOT IN过滤
* * @access public
* @param string $field 字段名 * @param string $field 字段名
* @param array $value 数据 * @param array $value 数据
* @return static<TKey, TValue> * @return static
*/ */
public function whereNotIn(string $field, array $value) public function whereNotIn(string $field, array $value)
{ {
@@ -457,10 +453,10 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* BETWEEN 过滤 * BETWEEN 过滤
* * @access public
* @param string $field 字段名 * @param string $field 字段名
* @param mixed $value 数据 * @param mixed $value 数据
* @return static<TKey, TValue> * @return static
*/ */
public function whereBetween(string $field, $value) public function whereBetween(string $field, $value)
{ {
@@ -469,10 +465,10 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* NOT BETWEEN 过滤 * NOT BETWEEN 过滤
* * @access public
* @param string $field 字段名 * @param string $field 字段名
* @param mixed $value 数据 * @param mixed $value 数据
* @return static<TKey, TValue> * @return static
*/ */
public function whereNotBetween(string $field, $value) public function whereNotBetween(string $field, $value)
{ {
@@ -481,12 +477,12 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 返回数据中指定的一列 * 返回数据中指定的一列
* * @access public
* @param string|null $columnKey 键名 * @param string|null $columnKey 键名
* @param string|null $indexKey 作为索引值的列 * @param string|null $indexKey 作为索引值的列
* @return array * @return array
*/ */
public function column(?string $columnKey, ?string $indexKey = null) public function column( ? string $columnKey, string $indexKey = null)
{ {
return array_column($this->items, $columnKey, $indexKey); return array_column($this->items, $columnKey, $indexKey);
} }
@@ -494,10 +490,11 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 对数组排序 * 对数组排序
* *
* @access public
* @param callable|null $callback 回调 * @param callable|null $callback 回调
* @return static<TKey, TValue> * @return static
*/ */
public function sort(?callable $callback = null) public function sort(callable $callback = null)
{ {
$items = $this->items; $items = $this->items;
@@ -512,7 +509,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 指定字段排序 * 指定字段排序
* * @access public
* @param string $field 排序字段 * @param string $field 排序字段
* @param string $order 排序 * @param string $order 排序
* @return $this * @return $this
@@ -523,14 +520,15 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
$fieldA = $a[$field] ?? null; $fieldA = $a[$field] ?? null;
$fieldB = $b[$field] ?? null; $fieldB = $b[$field] ?? null;
return 'desc' == strtolower($order) ? ($fieldB <=> $fieldA) : ($fieldA <=> $fieldB); return 'desc' == strtolower($order) ? intval($fieldB > $fieldA) : intval($fieldA > $fieldB);
}); });
} }
/** /**
* 将数组打乱 * 将数组打乱
* *
* @return static<TKey, TValue> * @access public
* @return static
*/ */
public function shuffle() public function shuffle()
{ {
@@ -544,11 +542,12 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 获取第一个单元数据 * 获取第一个单元数据
* *
* @access public
* @param callable|null $callback * @param callable|null $callback
* @param null $default * @param null $default
* @return TValue * @return mixed
*/ */
public function first(?callable $callback = null, $default = null) public function first(callable $callback = null, $default = null)
{ {
return Arr::first($this->items, $callback, $default); return Arr::first($this->items, $callback, $default);
} }
@@ -556,11 +555,12 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 获取最后一个单元数据 * 获取最后一个单元数据
* *
* @access public
* @param callable|null $callback * @param callable|null $callback
* @param null $default * @param null $default
* @return TValue * @return mixed
*/ */
public function last(?callable $callback = null, $default = null) public function last(callable $callback = null, $default = null)
{ {
return Arr::last($this->items, $callback, $default); return Arr::last($this->items, $callback, $default);
} }
@@ -568,41 +568,30 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 截取数组 * 截取数组
* *
* @access public
* @param int $offset 起始位置 * @param int $offset 起始位置
* @param int|null $length 截取长度 * @param int $length 截取长度
* @param bool $preserveKeys preserveKeys * @param bool $preserveKeys preserveKeys
* @return static<TKey, TValue> * @return static
*/ */
public function slice(int $offset, ?int $length = null, bool $preserveKeys = false) public function slice(int $offset, int $length = null, bool $preserveKeys = false)
{ {
return new static(array_slice($this->items, $offset, $length, $preserveKeys)); return new static(array_slice($this->items, $offset, $length, $preserveKeys));
} }
/** // ArrayAccess
* @param TKey $key
* @return bool
*/
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function offsetExists($offset) : bool public function offsetExists($offset) : bool
{ {
return array_key_exists($offset, $this->items); return array_key_exists($offset, $this->items);
} }
/**
* @param TKey $offset
* @return TValue
*/
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function offsetGet($offset) public function offsetGet($offset)
{ {
return $this->items[$offset]; return $this->items[$offset];
} }
/**
* @param TKey|null $offset
* @param TValue $value
* @return void
*/
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function offsetSet($offset, $value) public function offsetSet($offset, $value)
{ {
@@ -613,10 +602,6 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
} }
} }
/**
* @param TKey $offset
* @return void
*/
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function offsetUnset($offset) public function offsetUnset($offset)
{ {
@@ -629,9 +614,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
return count($this->items); return count($this->items);
} }
/** //IteratorAggregate
* @return ArrayIterator<TKey, TValue>
*/
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function getIterator(): Traversable public function getIterator(): Traversable
{ {
@@ -647,7 +630,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 转换当前数据集为JSON字符串 * 转换当前数据集为JSON字符串
* * @access public
* @param integer $options json参数 * @param integer $options json参数
* @return string * @return string
*/ */
@@ -664,6 +647,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/** /**
* 转换成数组 * 转换成数组
* *
* @access public
* @param mixed $items 数据 * @param mixed $items 数据
* @return array * @return array
*/ */

View File

@@ -16,15 +16,12 @@ if (!function_exists('throw_if')) {
/** /**
* 按条件抛异常 * 按条件抛异常
* *
* @template TValue * @param mixed $condition
* @template TException of \Throwable * @param Throwable|string $exception
* @param array ...$parameters
* @return mixed
* *
* @param TValue $condition * @throws Throwable
* @param TException|class-string<TException>|string $exception
* @param mixed ...$parameters
* @return TValue
*
* @throws TException
*/ */
function throw_if($condition, $exception, ...$parameters) function throw_if($condition, $exception, ...$parameters)
{ {
@@ -40,15 +37,11 @@ if (!function_exists('throw_unless')) {
/** /**
* 按条件抛异常 * 按条件抛异常
* *
* @template TValue * @param mixed $condition
* @template TException of \Throwable * @param Throwable|string $exception
* * @param array ...$parameters
* @param TValue $condition * @return mixed
* @param TException|class-string<TException>|string $exception * @throws Throwable
* @param mixed ...$parameters
* @return TValue
*
* @throws TException
*/ */
function throw_unless($condition, $exception, ...$parameters) function throw_unless($condition, $exception, ...$parameters)
{ {
@@ -64,11 +57,9 @@ if (!function_exists('tap')) {
/** /**
* 对一个值调用给定的闭包,然后返回该值 * 对一个值调用给定的闭包,然后返回该值
* *
* @template TValue * @param mixed $value
* * @param callable|null $callback
* @param TValue $value * @return mixed
* @param (callable(TValue): mixed)|null $callback
* @return TValue
*/ */
function tap($value, $callback = null) function tap($value, $callback = null)
{ {
@@ -86,10 +77,8 @@ if (!function_exists('value')) {
/** /**
* Return the default value of the given value. * Return the default value of the given value.
* *
* @template TValue * @param mixed $value
* * @return mixed
* @param TValue|\Closure(): TValue $value
* @return TValue
*/ */
function value($value) function value($value)
{ {
@@ -288,30 +277,3 @@ if (!function_exists('class_uses_recursive')) {
return array_unique($results); return array_unique($results);
} }
} }
if (!function_exists('array_is_list')) {
/**
* 判断数组是否为list
*
* @param array $array 数据
* @return bool
*/
function array_is_list(array $array): bool
{
return array_values($array) === $array;
}
}
if (!function_exists('json_validate')) {
/**
* 判断是否为有效json数据
*
* @param string $string 数据
* @return bool
*/
function json_validate(string $string): bool
{
json_decode($string);
return json_last_error() === JSON_ERROR_NONE;
}
}

View File

@@ -32,9 +32,9 @@ class Arr
/** /**
* Add an element to an array using "dot" notation if it doesn't exist. * Add an element to an array using "dot" notation if it doesn't exist.
* *
* @param array $array * @param array $array
* @param string $key * @param string $key
* @param mixed $value * @param mixed $value
* @return array * @return array
*/ */
public static function add($array, $key, $value) public static function add($array, $key, $value)
@@ -110,7 +110,7 @@ class Arr
/** /**
* Flatten a multi-dimensional associative array with dots. * Flatten a multi-dimensional associative array with dots.
* *
* @param array $array * @param array $array
* @param string $prepend * @param string $prepend
* @return array * @return array
*/ */
@@ -132,7 +132,7 @@ class Arr
/** /**
* Get all of the given array except for a specified array of keys. * Get all of the given array except for a specified array of keys.
* *
* @param array $array * @param array $array
* @param array|string $keys * @param array|string $keys
* @return array * @return array
*/ */
@@ -147,7 +147,7 @@ class Arr
* Determine if the given key exists in the provided array. * Determine if the given key exists in the provided array.
* *
* @param \ArrayAccess|array $array * @param \ArrayAccess|array $array
* @param string|int $key * @param string|int $key
* @return bool * @return bool
*/ */
public static function exists($array, $key) public static function exists($array, $key)
@@ -162,12 +162,12 @@ class Arr
/** /**
* Return the first element in an array passing a given truth test. * Return the first element in an array passing a given truth test.
* *
* @param array $array * @param array $array
* @param callable|null $callback * @param callable|null $callback
* @param mixed $default * @param mixed $default
* @return mixed * @return mixed
*/ */
public static function first($array, ?callable $callback = null, $default = null) public static function first($array, callable $callback = null, $default = null)
{ {
if (is_null($callback)) { if (is_null($callback)) {
if (empty($array)) { if (empty($array)) {
@@ -191,12 +191,12 @@ class Arr
/** /**
* Return the last element in an array passing a given truth test. * Return the last element in an array passing a given truth test.
* *
* @param array $array * @param array $array
* @param callable|null $callback * @param callable|null $callback
* @param mixed $default * @param mixed $default
* @return mixed * @return mixed
*/ */
public static function last($array, ?callable $callback = null, $default = null) public static function last($array, callable $callback = null, $default = null)
{ {
if (is_null($callback)) { if (is_null($callback)) {
return empty($array) ? value($default) : end($array); return empty($array) ? value($default) : end($array);
@@ -209,7 +209,7 @@ class Arr
* Flatten a multi-dimensional array into a single level. * Flatten a multi-dimensional array into a single level.
* *
* @param array $array * @param array $array
* @param int $depth * @param int $depth
* @return array * @return array
*/ */
public static function flatten($array, $depth = INF) public static function flatten($array, $depth = INF)
@@ -234,7 +234,7 @@ class Arr
/** /**
* Remove one or many array items from a given array using "dot" notation. * Remove one or many array items from a given array using "dot" notation.
* *
* @param array $array * @param array $array
* @param array|string $keys * @param array|string $keys
* @return void * @return void
*/ */
@@ -279,8 +279,8 @@ class Arr
* Get an item from an array using "dot" notation. * Get an item from an array using "dot" notation.
* *
* @param \ArrayAccess|array $array * @param \ArrayAccess|array $array
* @param string $key * @param string $key
* @param mixed $default * @param mixed $default
* @return mixed * @return mixed
*/ */
public static function get($array, $key, $default = null) public static function get($array, $key, $default = null)
@@ -316,7 +316,7 @@ class Arr
* Check if an item or items exist in an array using "dot" notation. * Check if an item or items exist in an array using "dot" notation.
* *
* @param \ArrayAccess|array $array * @param \ArrayAccess|array $array
* @param string|array $keys * @param string|array $keys
* @return bool * @return bool
*/ */
public static function has($array, $keys) public static function has($array, $keys)
@@ -356,13 +356,15 @@ class Arr
*/ */
public static function isAssoc(array $array) public static function isAssoc(array $array)
{ {
return !array_is_list($array); $keys = array_keys($array);
return array_keys($keys) !== $keys;
} }
/** /**
* Get a subset of the items from the given array. * Get a subset of the items from the given array.
* *
* @param array $array * @param array $array
* @param array|string $keys * @param array|string $keys
* @return array * @return array
*/ */
@@ -374,8 +376,8 @@ class Arr
/** /**
* Pluck an array of values from an array. * Pluck an array of values from an array.
* *
* @param array $array * @param array $array
* @param string|array $value * @param string|array $value
* @param string|array|null $key * @param string|array|null $key
* @return array * @return array
*/ */
@@ -410,7 +412,7 @@ class Arr
/** /**
* Explode the "value" and "key" arguments passed to "pluck". * Explode the "value" and "key" arguments passed to "pluck".
* *
* @param string|array $value * @param string|array $value
* @param string|array|null $key * @param string|array|null $key
* @return array * @return array
*/ */
@@ -445,9 +447,9 @@ class Arr
/** /**
* Get a value from the array, and remove it. * Get a value from the array, and remove it.
* *
* @param array $array * @param array $array
* @param string $key * @param string $key
* @param mixed $default * @param mixed $default
* @return mixed * @return mixed
*/ */
public static function pull(&$array, $key, $default = null) public static function pull(&$array, $key, $default = null)
@@ -462,7 +464,7 @@ class Arr
/** /**
* Get one or a specified number of random values from an array. * Get one or a specified number of random values from an array.
* *
* @param array $array * @param array $array
* @param int|null $number * @param int|null $number
* @return mixed * @return mixed
* *
@@ -504,9 +506,9 @@ class Arr
* *
* If no key is given to the method, the entire array will be replaced. * If no key is given to the method, the entire array will be replaced.
* *
* @param array $array * @param array $array
* @param string $key * @param string $key
* @param mixed $value * @param mixed $value
* @return array * @return array
*/ */
public static function set(&$array, $key, $value) public static function set(&$array, $key, $value)
@@ -538,7 +540,7 @@ class Arr
/** /**
* Shuffle the given array and return the result. * Shuffle the given array and return the result.
* *
* @param array $array * @param array $array
* @param int|null $seed * @param int|null $seed
* @return array * @return array
*/ */
@@ -560,7 +562,7 @@ class Arr
/** /**
* Sort the array using the given callback or "dot" notation. * Sort the array using the given callback or "dot" notation.
* *
* @param array $array * @param array $array
* @param callable|string|null $callback * @param callable|string|null $callback
* @return array * @return array
*/ */
@@ -606,7 +608,7 @@ class Arr
/** /**
* Filter the array using the given callback. * Filter the array using the given callback.
* *
* @param array $array * @param array $array
* @param callable $callback * @param callable $callback
* @return array * @return array
*/ */
@@ -629,41 +631,4 @@ class Arr
return is_array($value) ? $value : [$value]; return is_array($value) ? $value : [$value];
} }
}
/**
* Recursively merge arrays.
* If the value is an associative array, it will be merged recursively.
* If the value is an indexed array, it will be replaced entirely.
*
* @param array ...$arrays
* @return array
*/
public static function mergeDeep(array ...$arrays): array
{
$result = [];
foreach ($arrays as $array) {
foreach ($array as $key => $value) {
if (isset($result[$key]) && is_array($result[$key]) && is_array($value)) {
// 只有当两个数组都是关联数组时才递归合并
if (self::isAssoc($result[$key]) && self::isAssoc($value)) {
$result[$key] = self::mergeDeep(
$result[$key],
$value
);
} else {
// 如果任一数组是索引数组,则直接覆盖
$result[$key] = $value;
}
} else {
$result[$key] = $value;
}
}
}
return $result;
}
public static function flatMap(callable $fn, array $array): array
{
return array_merge(...array_map($fn, $array));
}
}

View File

@@ -80,7 +80,7 @@ class Str
* @param string $addChars * @param string $addChars
* @return string * @return string
*/ */
public static function random(int $length = 6, ?int $type = null, string $addChars = ''): string public static function random(int $length = 6, int $type = null, string $addChars = ''): string
{ {
$str = ''; $str = '';
switch ($type) { switch ($type) {
@@ -158,7 +158,7 @@ class Str
* @param int|null $length * @param int|null $length
* @return string * @return string
*/ */
public static function substr(string $string, int $start, ?int $length = null): string public static function substr(string $string, int $start, int $length = null): string
{ {
return mb_substr($string, $start, $length, 'UTF-8'); return mb_substr($string, $start, $length, 'UTF-8');
} }

View File

@@ -55,7 +55,7 @@ class ArrTest extends TestCase
public function testDivide() public function testDivide()
{ {
[$keys, $values] = Arr::divide(['name' => 'ThinkPHP']); list($keys, $values) = Arr::divide(['name' => 'ThinkPHP']);
$this->assertSame(['name'], $keys); $this->assertSame(['name'], $keys);
$this->assertSame(['ThinkPHP'], $values); $this->assertSame(['ThinkPHP'], $values);
} }
@@ -109,7 +109,7 @@ class ArrTest extends TestCase
public function testLast() public function testLast()
{ {
$array = [100, 200, 300]; $array = [100, 200, 300];
$last = Arr::last($array, function ($value) { $last = Arr::last($array, function ($value) {
return $value < 250; return $value < 250;
}); });
$this->assertSame(200, $last); $this->assertSame(200, $last);
@@ -234,17 +234,17 @@ class ArrTest extends TestCase
public function testPull() public function testPull()
{ {
$array = ['name' => 'ThinkPHP', 'price' => 100]; $array = ['name' => 'ThinkPHP', 'price' => 100];
$name = Arr::pull($array, 'name'); $name = Arr::pull($array, 'name');
$this->assertSame('ThinkPHP', $name); $this->assertSame('ThinkPHP', $name);
$this->assertSame(['price' => 100], $array); $this->assertSame(['price' => 100], $array);
// Only works on first level keys // Only works on first level keys
$array = ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane']; $array = ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane'];
$name = Arr::pull($array, 'i@example.com'); $name = Arr::pull($array, 'i@example.com');
$this->assertSame('Joe', $name); $this->assertSame('Joe', $name);
$this->assertSame(['jack@localhost' => 'Jane'], $array); $this->assertSame(['jack@localhost' => 'Jane'], $array);
// Does not work for nested keys // Does not work for nested keys
$array = ['emails' => ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane']]; $array = ['emails' => ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane']];
$name = Arr::pull($array, 'emails.i@example.com'); $name = Arr::pull($array, 'emails.i@example.com');
$this->assertNull($name); $this->assertNull($name);
$this->assertSame(['emails' => ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane']], $array); $this->assertSame(['emails' => ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane']], $array);
} }
@@ -331,42 +331,12 @@ class ArrTest extends TestCase
public function testWrap() public function testWrap()
{ {
$string = 'a'; $string = 'a';
$array = ['a']; $array = ['a'];
$object = new stdClass(); $object = new stdClass();
$object->value = 'a'; $object->value = 'a';
$this->assertSame(['a'], Arr::wrap($string)); $this->assertSame(['a'], Arr::wrap($string));
$this->assertSame($array, Arr::wrap($array)); $this->assertSame($array, Arr::wrap($array));
$this->assertSame([$object], Arr::wrap($object)); $this->assertSame([$object], Arr::wrap($object));
} }
public function testMergeDeep()
{
$this->assertSame(
[
'a' => [
'c' => [2],
'e' => 5,
'f' => 4,
],
'x' => 3,
],
Arr::mergeDeep(
[
'a' => [
'c' => [1],
'e' => 5,
],
'x' => 4,
],
[
'a' => [
'c' => [2],
'f' => 4,
],
'x' => 3,
]
)
);
}
} }

View File

@@ -1,32 +1,33 @@
<?php <?php
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ] // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 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 ) // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com> // | Author: liu21st <liu21st@gmail.com>
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
namespace think\app; namespace think\app;
use think\Service as BaseService; use think\Service as BaseService;
class Service extends BaseService class Service extends BaseService
{ {
public function boot() public function boot()
{ {
$this->app->event->listen('HttpRun', function () { $this->app->event->listen('HttpRun', function () {
$this->app->middleware->add(MultiApp::class);
}); $this->app->middleware->add(MultiApp::class);
});
$this->commands([
'build' => command\Build::class, $this->commands([
'clear' => command\Clear::class, 'build' => command\Build::class,
]); 'clear' => command\Clear::class,
]);
$this->app->bind([
'think\route\Url' => Url::class, $this->app->bind([
]); 'think\route\Url' => Url::class,
} ]);
} }
}

View File

@@ -52,6 +52,12 @@ class DbManager
*/ */
protected $listen = []; protected $listen = [];
/**
* SQL日志
* @var array
*/
protected $dbLog = [];
/** /**
* 查询次数 * 查询次数
* @var int * @var int
@@ -161,6 +167,8 @@ class DbManager
{ {
if ($this->log) { if ($this->log) {
$this->log->log($type, $log); $this->log->log($type, $log);
} else {
$this->dbLog[$type][] = $log;
} }
} }
@@ -172,7 +180,12 @@ class DbManager
*/ */
public function getDbLog(bool $clear = false): array public function getDbLog(bool $clear = false): array
{ {
return []; $logs = $this->dbLog;
if ($clear) {
$this->dbLog = [];
}
return $logs;
} }
/** /**
@@ -279,17 +292,16 @@ class DbManager
/** /**
* 更新查询次数 * 更新查询次数
* @deprecated
* @access public * @access public
* @return void * @return void
*/ */
public function updateQueryTimes(): void public function updateQueryTimes(): void
{ {
$this->queryTimes++;
} }
/** /**
* 重置查询次数 * 重置查询次数
* @deprecated
* @access public * @access public
* @return void * @return void
*/ */
@@ -300,7 +312,6 @@ class DbManager
/** /**
* 获得查询次数 * 获得查询次数
* @deprecated
* @access public * @access public
* @return integer * @return integer
*/ */
@@ -330,16 +341,6 @@ class DbManager
return $this->listen; return $this->listen;
} }
/**
* 获取所有连接实列
* @access public
* @return array
*/
public function getInstance(): array
{
return $this->instance;
}
/** /**
* 注册回调方法 * 注册回调方法
* @access public * @access public

View File

@@ -121,12 +121,6 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
*/ */
private $lazySave = false; private $lazySave = false;
/**
* 缓存自动更新标识
* @var bool|string
*/
protected $cacheKey = false;
/** /**
* Db对象 * Db对象
* @var DbManager * @var DbManager
@@ -341,18 +335,6 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
return $this; return $this;
} }
/**
* 设置当前查询的自动缓存标识
* @access public
* @param string|bool $key 缓存标识
* @return $this
*/
public function setCacheKey($key)
{
$this->cacheKey = $key;
return $this;
}
/** /**
* 获取当前模型的数据表后缀 * 获取当前模型的数据表后缀
* @access public * @access public
@@ -659,7 +641,7 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
$result = $db->where($where) $result = $db->where($where)
->strict(false) ->strict(false)
->cache($this->cacheKey) ->cache(true)
->setOption('key', $this->key) ->setOption('key', $this->key)
->field($allowFields) ->field($allowFields)
->update($data); ->update($data);
@@ -787,20 +769,16 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
$pk = $this->getPk(); $pk = $this->getPk();
if (is_string($pk) && $replace) {
$auto = true;
}
$result = []; $result = [];
$suffix = $this->getSuffix(); $suffix = $this->getSuffix();
foreach ($dataSet as $key => $data) { foreach ($dataSet as $key => $data) {
if ($replace) { if ($this->exists || (!empty($auto) && isset($data[$pk]))) {
$exists = true;
foreach ((array) $pk as $field) {
if (!isset($data[$field])) {
$exists = false;
}
}
}
if ($replace && !empty($exists)) {
$result[$key] = static::update($data, [], [], $suffix); $result[$key] = static::update($data, [], [], $suffix);
} else { } else {
$result[$key] = static::create($data, $this->field, $this->replace, $suffix); $result[$key] = static::create($data, $this->field, $this->replace, $suffix);
@@ -831,7 +809,7 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
$db->transaction(function () use ($where, $db) { $db->transaction(function () use ($where, $db) {
// 删除当前模型数据 // 删除当前模型数据
$db->where($where)->cache($this->cacheKey)->delete(); $db->where($where)->delete();
// 关联删除 // 关联删除
if (!empty($this->relationWrite)) { if (!empty($this->relationWrite)) {

View File

@@ -377,19 +377,6 @@ abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, J
return $this->items; return $this->items;
} }
/**
* 设置数据集
*
* @param Collection $items
* @return $this
*/
public function setCollection(Collection $items)
{
$this->items = $items;
return $this;
}
public function isEmpty(): bool public function isEmpty(): bool
{ {
return $this->items->isEmpty(); return $this->items->isEmpty();

View File

@@ -770,9 +770,10 @@ abstract class BaseQuery
* @param mixed $key 缓存key * @param mixed $key 缓存key
* @param integer|\DateTime $expire 缓存有效期 * @param integer|\DateTime $expire 缓存有效期
* @param string|array $tag 缓存标签 * @param string|array $tag 缓存标签
* @param bool $always 始终缓存
* @return $this * @return $this
*/ */
public function cache($key = true, $expire = null, $tag = null) public function cache($key = true, $expire = null, $tag = null, bool $always = false)
{ {
if (false === $key || !$this->getConnection()->getCache()) { if (false === $key || !$this->getConnection()->getCache()) {
return $this; return $this;
@@ -783,7 +784,8 @@ abstract class BaseQuery
$key = true; $key = true;
} }
$this->options['cache'] = [$key, $expire, $tag ?: $this->getTable()]; $this->options['cache'] = [$key, $expire, $tag];
$this->options['cache_always'] = $always;
return $this; return $this;
} }
@@ -798,23 +800,7 @@ abstract class BaseQuery
*/ */
public function cacheAlways($key = true, $expire = null, $tag = null) public function cacheAlways($key = true, $expire = null, $tag = null)
{ {
$this->options['cache_always'] = true; return $this->cache($key, $expire, $tag, true);
return $this->cache($key, $expire, $tag);
}
/**
* 强制更新缓存
*
* @param mixed $key 缓存key
* @param int|\DateTime $expire 缓存有效期
* @param string|array $tag 缓存标签
*
* @return $this
*/
public function cacheForce($key = true, $expire = null, $tag = null)
{
$this->options['force_cache'] = true;
return $this->cache($key, $expire, $tag);
} }
/** /**
@@ -1040,23 +1026,6 @@ abstract class BaseQuery
return $this->connection->insertAll($this, $dataSet, $limit); return $this->connection->insertAll($this, $dataSet, $limit);
} }
/**
* 批量插入记录
* @access public
* @param array $keys 键值
* @param array $values 数据
* @param integer $limit 每次写入数据限制
* @return integer
*/
public function insertAllByKeys(array $keys, array $values, int $limit = 0): int
{
if (empty($limit) && !empty($this->options['limit']) && is_numeric($this->options['limit'])) {
$limit = (int) $this->options['limit'];
}
return $this->connection->insertAllByKeys($this, $keys, $values, $limit);
}
/** /**
* 通过Select方式插入记录 * 通过Select方式插入记录
* @access public * @access public

View File

@@ -158,8 +158,7 @@ abstract class Builder
if (false !== strpos($key, '->')) { if (false !== strpos($key, '->')) {
[$key, $name] = explode('->', $key, 2); [$key, $name] = explode('->', $key, 2);
$item = $this->parseKey($query, $key); $item = $this->parseKey($query, $key);
$result[$item] = 'json_set(' . $item . ', \'$.' . $name . '\', ' . $this->parseDataBind($query, $key . '->' . $name, $val, $bind) . ')';
$result[$item . '->' . $name] = 'json_set(' . $item . ', \'$.' . $name . '\', ' . $this->parseDataBind($query, $key . '->' . $name, $val, $bind) . ')';
} elseif (false === strpos($key, '.') && !in_array($key, $fields, true)) { } elseif (false === strpos($key, '.') && !in_array($key, $fields, true)) {
if ($options['strict']) { if ($options['strict']) {
throw new Exception('fields not exists:[' . $key . ']'); throw new Exception('fields not exists:[' . $key . ']');
@@ -177,11 +176,7 @@ abstract class Builder
} }
} elseif (is_scalar($val)) { } elseif (is_scalar($val)) {
// 过滤非标量数据 // 过滤非标量数据
if (!$query->isAutoBind() && PDO::PARAM_STR == $bind[$key]) { $result[$item] = $this->parseDataBind($query, $key, $val, $bind);
$val = '\'' . $val . '\'';
}
$result[$item] = !$query->isAutoBind() ? $val : $this->parseDataBind($query, $key, $val, $bind);
} }
} }
@@ -766,22 +761,17 @@ abstract class Builder
if (count($value) === 0) { if (count($value) === 0) {
return 'IN' == $exp ? '0 = 1' : '1 = 1'; return 'IN' == $exp ? '0 = 1' : '1 = 1';
} }
$array = [];
if ($query->isAutoBind()) { foreach ($value as $v) {
$array = []; $name = $query->bindValue($v, $bindType);
foreach ($value as $v) { $array[] = ':' . $name;
$name = $query->bindValue($v, $bindType);
$array[] = ':' . $name;
}
$value = implode(',', $array);
} elseif (PDO::PARAM_STR == $bindType) {
$value = '\'' . implode('\',\'', $value) . '\'';
} else {
$value = implode(',', $value);
} }
if (false === strpos($value, ',')) { if (count($array) == 1) {
return $key . ('IN' == $exp ? ' = ' : ' <> ') . $value; return $key . ('IN' == $exp ? ' = ' : ' <> ') . $array[0];
} else {
$value = implode(',', $array);
} }
} }
@@ -1149,8 +1139,7 @@ abstract class Builder
$this->parseComment($query, $options['comment']), $this->parseComment($query, $options['comment']),
$this->parseForce($query, $options['force']), $this->parseForce($query, $options['force']),
], ],
$this->selectSql $this->selectSql);
);
} }
/** /**
@@ -1182,8 +1171,7 @@ abstract class Builder
implode(' , ', $values), implode(' , ', $values),
$this->parseComment($query, $options['comment']), $this->parseComment($query, $options['comment']),
], ],
$this->insertSql $this->insertSql);
);
} }
/** /**
@@ -1234,57 +1222,9 @@ abstract class Builder
implode(' UNION ALL ', $values), implode(' UNION ALL ', $values),
$this->parseComment($query, $options['comment']), $this->parseComment($query, $options['comment']),
], ],
$this->insertAllSql $this->insertAllSql);
);
} }
/**
* 生成insertall SQL
* @access public
* @param Query $query 查询对象
* @param array $keys 字段名
* @param array $datas 数据
* @return string
*/
public function insertAllByKeys(Query $query, array $keys, array $datas): string
{
$options = $query->getOptions();
// 获取绑定信息
$bind = $query->getFieldsBindType();
$fields = [];
$values = [];
foreach ($keys as $field) {
$fields[] = $this->parseKey($query, $field);
}
foreach ($datas as $data) {
foreach ($data as $key => &$val) {
if (!$query->isAutoBind()) {
$val = PDO::PARAM_STR == $bind[$keys[$key]] ? '\'' . $val . '\'' : $val;
} else {
$val = $this->parseDataBind($query, $keys[$key], $val, $bind);
}
}
$values[] = 'SELECT ' . implode(',', $data);
}
return str_replace(
['%INSERT%', '%TABLE%', '%EXTRA%', '%FIELD%', '%DATA%', '%COMMENT%'],
[
!empty($options['replace']) ? 'REPLACE' : 'INSERT',
$this->parseTable($query, $options['table']),
$this->parseExtra($query, $options['extra']),
implode(' , ', $fields),
implode(' UNION ALL ', $values),
$this->parseComment($query, $options['comment']),
],
$this->insertAllSql
);
}
/** /**
* 生成slect insert SQL * 生成slect insert SQL
* @access public * @access public
@@ -1336,8 +1276,7 @@ abstract class Builder
$this->parseLock($query, $options['lock']), $this->parseLock($query, $options['lock']),
$this->parseComment($query, $options['comment']), $this->parseComment($query, $options['comment']),
], ],
$this->updateSql $this->updateSql);
);
} }
/** /**
@@ -1363,7 +1302,6 @@ abstract class Builder
$this->parseLock($query, $options['lock']), $this->parseLock($query, $options['lock']),
$this->parseComment($query, $options['comment']), $this->parseComment($query, $options['comment']),
], ],
$this->deleteSql $this->deleteSql);
);
} }
} }

View File

@@ -8,7 +8,7 @@
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com> // | Author: liu21st <liu21st@gmail.com>
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
declare(strict_types=1); declare (strict_types = 1);
namespace think\db; namespace think\db;

View File

@@ -309,7 +309,7 @@ class Fetch
$this->query->setOption('soft_delete', null); $this->query->setOption('soft_delete', null);
$this->query->setOption('data', [$field => $condition]); $this->query->setOption('data', [$field => $condition]);
// 生成删除SQL语句 // 生成删除SQL语句
$sql = $this->builder->update($this->query); $sql = $this->builder->delete($this->query);
return $this->fetch($sql); return $this->fetch($sql);
} }
} }

View File

@@ -8,7 +8,7 @@
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com> // | Author: liu21st <liu21st@gmail.com>
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
declare(strict_types=1); declare (strict_types = 1);
namespace think\db; namespace think\db;
@@ -81,8 +81,6 @@ abstract class PDOConnection extends Connection
'break_reconnect' => false, 'break_reconnect' => false,
// 断线标识字符串 // 断线标识字符串
'break_match_str' => [], 'break_match_str' => [],
// 自动参数绑定
'auto_param_bind' => true,
]; ];
/** /**
@@ -354,13 +352,15 @@ abstract class PDOConnection extends Connection
if (!isset($this->info[$schema]) || $force) { if (!isset($this->info[$schema]) || $force) {
// 读取字段缓存 // 读取字段缓存
$cacheKey = $this->getSchemaCacheKey($schema); $cacheKey = $this->getSchemaCacheKey($schema);
if ($this->config['fields_cache'] && !empty($this->cache) && !$force) { $cacheField = $this->config['fields_cache'] && !empty($this->cache);
if ($cacheField && !$force) {
$info = $this->cache->get($cacheKey); $info = $this->cache->get($cacheKey);
} }
if (empty($info)) { if (empty($info)) {
$info = $this->getTableFieldsInfo($tableName); $info = $this->getTableFieldsInfo($tableName);
if (!empty($this->cache) && ($this->config['fields_cache'] || $force)) { if ($cacheField) {
$this->cache->set($cacheKey, $info); $this->cache->set($cacheKey, $info);
} }
} }
@@ -622,14 +622,15 @@ abstract class PDOConnection extends Connection
* @access public * @access public
* @param BaseQuery $query 查询对象 * @param BaseQuery $query 查询对象
* @param string $sql sql指令 * @param string $sql sql指令
* @param array $bind 参数绑定
* @param Model|null $model 模型对象实例 * @param Model|null $model 模型对象实例
* @param null $condition 查询条件 * @param null $condition 查询条件
* @return \Generator * @return \Generator
* @throws DbException * @throws DbException
*/ */
public function getCursor(BaseQuery $query, string $sql, $model = null, $condition = null) public function getCursor(BaseQuery $query, string $sql, array $bind = [], $model = null, $condition = null)
{ {
$this->queryPDOStatement($query, $sql); $this->queryPDOStatement($query, $sql, $bind);
// 返回结果集 // 返回结果集
while ($result = $this->PDOStatement->fetch($this->fetchType)) { while ($result = $this->PDOStatement->fetch($this->fetchType)) {
@@ -652,7 +653,7 @@ abstract class PDOConnection extends Connection
*/ */
public function query(string $sql, array $bind = [], bool $master = false): array public function query(string $sql, array $bind = [], bool $master = false): array
{ {
return $this->pdoQuery($this->newQuery()->bind($bind), $sql, $master); return $this->pdoQuery($this->newQuery(), $sql, $bind, $master);
} }
/** /**
@@ -665,7 +666,7 @@ abstract class PDOConnection extends Connection
*/ */
public function execute(string $sql, array $bind = []): int public function execute(string $sql, array $bind = []): int
{ {
return $this->pdoExecute($this->newQuery()->bind($bind), $sql, true); return $this->pdoExecute($this->newQuery(), $sql, $bind, true);
} }
/** /**
@@ -673,27 +674,25 @@ abstract class PDOConnection extends Connection
* @access protected * @access protected
* @param BaseQuery $query 查询对象 * @param BaseQuery $query 查询对象
* @param mixed $sql sql指令 * @param mixed $sql sql指令
* @param array $bind 参数绑定
* @param bool $master 主库读取 * @param bool $master 主库读取
* @return array * @return array
* @throws DbException * @throws DbException
*/ */
protected function pdoQuery(BaseQuery $query, $sql, bool $master = null): array protected function pdoQuery(BaseQuery $query, $sql, array $bind = [], bool $master = null): array
{ {
// 分析查询表达式 // 分析查询表达式
$query->parseOptions(); $query->parseOptions();
$bind = $query->getBind();
if ($query->getOptions('cache')) { if ($query->getOptions('cache')) {
// 检查查询缓存 // 检查查询缓存
$cacheItem = $this->parseCache($query, $query->getOptions('cache')); $cacheItem = $this->parseCache($query, $query->getOptions('cache'));
if (!$query->getOptions('force_cache')) { $key = $cacheItem->getKey();
$key = $cacheItem->getKey();
$data = $this->cache->get($key); $data = $this->cache->get($key);
if (null !== $data) { if (null !== $data) {
return $data; return $data;
}
} }
} }
@@ -731,10 +730,11 @@ abstract class PDOConnection extends Connection
*/ */
public function pdo(BaseQuery $query): PDOStatement public function pdo(BaseQuery $query): PDOStatement
{ {
$bind = $query->getBind();
// 生成查询SQL // 生成查询SQL
$sql = $this->builder->select($query); $sql = $this->builder->select($query);
return $this->queryPDOStatement($query, $sql); return $this->queryPDOStatement($query, $sql, $bind);
} }
/** /**
@@ -806,17 +806,18 @@ abstract class PDOConnection extends Connection
* @access protected * @access protected
* @param BaseQuery $query 查询对象 * @param BaseQuery $query 查询对象
* @param string $sql sql指令 * @param string $sql sql指令
* @param array $bind 参数绑定
* @param bool $origin 是否原生查询 * @param bool $origin 是否原生查询
* @return int * @return int
* @throws DbException * @throws DbException
*/ */
protected function pdoExecute(BaseQuery $query, string $sql, bool $origin = false): int protected function pdoExecute(BaseQuery $query, string $sql, array $bind = [], bool $origin = false): int
{ {
if ($origin) { if ($origin) {
$query->parseOptions(); $query->parseOptions();
} }
$this->queryPDOStatement($query->master(true), $sql); $this->queryPDOStatement($query->master(true), $sql, $bind);
if (!$origin && !empty($this->config['deploy']) && !empty($this->config['read_master'])) { if (!$origin && !empty($this->config['deploy']) && !empty($this->config['read_master'])) {
$this->readMaster = true; $this->readMaster = true;
@@ -843,13 +844,13 @@ abstract class PDOConnection extends Connection
/** /**
* @param BaseQuery $query * @param BaseQuery $query
* @param string $sql * @param string $sql
* @param array $bind
* @return PDOStatement * @return PDOStatement
* @throws DbException * @throws DbException
*/ */
protected function queryPDOStatement(BaseQuery $query, string $sql): PDOStatement protected function queryPDOStatement(BaseQuery $query, string $sql, array $bind = []): PDOStatement
{ {
$options = $query->getOptions(); $options = $query->getOptions();
$bind = $query->getBind();
$master = !empty($options['master']) ? true : false; $master = !empty($options['master']) ? true : false;
$procedure = !empty($options['procedure']) ? true : in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']); $procedure = !empty($options['procedure']) ? true : in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']);
@@ -897,7 +898,7 @@ abstract class PDOConnection extends Connection
$condition = $options['where']['AND'] ?? null; $condition = $options['where']['AND'] ?? null;
// 执行查询操作 // 执行查询操作
return $this->getCursor($query, $sql, $query->getModel(), $condition); return $this->getCursor($query, $sql, $query->getBind(), $query->getModel(), $condition);
} }
/** /**
@@ -937,7 +938,7 @@ abstract class PDOConnection extends Connection
$sql = $this->builder->insert($query); $sql = $this->builder->insert($query);
// 执行操作 // 执行操作
$result = '' == $sql ? 0 : $this->pdoExecute($query, $sql); $result = '' == $sql ? 0 : $this->pdoExecute($query, $sql, $query->getBind());
if ($result) { if ($result) {
$sequence = $options['sequence'] ?? null; $sequence = $options['sequence'] ?? null;
@@ -976,12 +977,13 @@ abstract class PDOConnection extends Connection
*/ */
public function insertAll(BaseQuery $query, array $dataSet = [], int $limit = 0): int public function insertAll(BaseQuery $query, array $dataSet = [], int $limit = 0): int
{ {
$query->parseOptions();
if (!is_array(reset($dataSet))) { if (!is_array(reset($dataSet))) {
return 0; return 0;
} }
$options = $query->parseOptions();
$replace = !empty($options['replace']);
if (0 === $limit && count($dataSet) >= 5000) { if (0 === $limit && count($dataSet) >= 5000) {
$limit = 1000; $limit = 1000;
} }
@@ -995,8 +997,8 @@ abstract class PDOConnection extends Connection
$count = 0; $count = 0;
foreach ($array as $item) { foreach ($array as $item) {
$sql = $this->builder->insertAll($query, $item); $sql = $this->builder->insertAll($query, $item, $replace);
$count += $this->pdoExecute($query, $sql); $count += $this->pdoExecute($query, $sql, $query->getBind());
} }
// 提交事务 // 提交事务
@@ -1009,56 +1011,9 @@ abstract class PDOConnection extends Connection
return $count; return $count;
} }
$sql = $this->builder->insertAll($query, $dataSet); $sql = $this->builder->insertAll($query, $dataSet, $replace);
return $this->pdoExecute($query, $sql); return $this->pdoExecute($query, $sql, $query->getBind());
}
/**
* 批量插入记录
* @access public
* @param BaseQuery $query 查询对象
* @param array $keys 键值
* @param array $values 数据
* @param integer $limit 每次写入数据限制
* @return integer
* @throws \Exception
* @throws \Throwable
*/
public function insertAllByKeys(BaseQuery $query, array $keys, array $values, int $limit = 0): int
{
$query->parseOptions();
if (0 === $limit && count($values) >= 5000) {
$limit = 1000;
}
if ($limit) {
// 分批写入 自动启动事务支持
$this->startTrans();
try {
$array = array_chunk($values, $limit, true);
$count = 0;
foreach ($array as $item) {
$sql = $this->builder->insertAllByKeys($query, $keys, $item);
$count += $this->pdoExecute($query, $sql);
}
// 提交事务
$this->commit();
} catch (\Exception | \Throwable $e) {
$this->rollback();
throw $e;
}
return $count;
}
$sql = $this->builder->insertAllByKeys($query, $keys, $values);
return $this->pdoExecute($query, $sql);
} }
/** /**
@@ -1077,7 +1032,7 @@ abstract class PDOConnection extends Connection
$sql = $this->builder->selectInsert($query, $fields, $table); $sql = $this->builder->selectInsert($query, $fields, $table);
return $this->pdoExecute($query, $sql); return $this->pdoExecute($query, $sql, $query->getBind());
} }
/** /**
@@ -1095,7 +1050,7 @@ abstract class PDOConnection extends Connection
$sql = $this->builder->update($query); $sql = $this->builder->update($query);
// 执行操作 // 执行操作
$result = '' == $sql ? 0 : $this->pdoExecute($query, $sql); $result = '' == $sql ? 0 : $this->pdoExecute($query, $sql, $query->getBind());
if ($result) { if ($result) {
$this->db->trigger('after_update', $query); $this->db->trigger('after_update', $query);
@@ -1120,7 +1075,7 @@ abstract class PDOConnection extends Connection
$sql = $this->builder->delete($query); $sql = $this->builder->delete($query);
// 执行操作 // 执行操作
$result = $this->pdoExecute($query, $sql); $result = $this->pdoExecute($query, $sql, $query->getBind());
if ($result) { if ($result) {
$this->db->trigger('after_delete', $query); $this->db->trigger('after_delete', $query);
@@ -1154,13 +1109,10 @@ abstract class PDOConnection extends Connection
if (!empty($options['cache'])) { if (!empty($options['cache'])) {
$cacheItem = $this->parseCache($query, $options['cache'], 'value'); $cacheItem = $this->parseCache($query, $options['cache'], 'value');
$key = $cacheItem->getKey();
if (!$query->getOptions('force_cache')) { if ($this->cache->has($key)) {
$key = $cacheItem->getKey(); return $this->cache->get($key);
if ($this->cache->has($key)) {
return $this->cache->get($key);
}
} }
} }
@@ -1233,13 +1185,13 @@ abstract class PDOConnection extends Connection
$key = null; $key = null;
} }
if (is_string($column)) { if (\is_string($column)) {
$column = trim($column); $column = \trim($column);
if ('*' !== $column) { if ('*' !== $column) {
$column = array_map('trim', explode(',', $column)); $column = \array_map('\trim', \explode(',', $column));
} }
} elseif (is_array($column)) { } elseif (\is_array($column)) {
if (in_array('*', $column)) { if (\in_array('*', $column)) {
$column = '*'; $column = '*';
} }
} else { } else {
@@ -1247,7 +1199,7 @@ abstract class PDOConnection extends Connection
} }
$field = $column; $field = $column;
if ('*' !== $column && $key && !in_array($key, $column)) { if ('*' !== $column && $key && !\in_array($key, $column)) {
$field[] = $key; $field[] = $key;
} }
@@ -1256,12 +1208,10 @@ abstract class PDOConnection extends Connection
if (!empty($options['cache'])) { if (!empty($options['cache'])) {
// 判断查询缓存 // 判断查询缓存
$cacheItem = $this->parseCache($query, $options['cache'], 'column'); $cacheItem = $this->parseCache($query, $options['cache'], 'column');
if (!$query->getOptions('force_cache')) { $name = $cacheItem->getKey();
$name = $cacheItem->getKey();
if ($this->cache->has($name)) { if ($this->cache->has($name)) {
return $this->cache->get($name); return $this->cache->get($name);
}
} }
} }
@@ -1284,23 +1234,19 @@ abstract class PDOConnection extends Connection
if (empty($resultSet)) { if (empty($resultSet)) {
$result = []; $result = [];
} elseif ('*' !== $column && count($column) === 1) { } elseif ('*' !== $column && \count($column) === 1) {
$column = array_shift($column); $column = \array_shift($column);
if (strpos($column, ' ')) { if (\strpos($column, ' ')) {
$column = substr(strrchr(trim($column), ' '), 1); $column = \substr(\strrchr(\trim($column), ' '), 1);
} }
if (strpos($column, '.')) { if (\strpos($column, '.')) {
[$alias, $column] = explode('.', $column); [$alias, $column] = \explode('.', $column);
} }
if (strpos($column, '->')) { $result = \array_column($resultSet, $column, $key);
$column = $this->builder->parseKey($query, $column);
}
$result = array_column($resultSet, $column, $key);
} elseif ($key) { } elseif ($key) {
$result = array_column($resultSet, null, $key); $result = \array_column($resultSet, null, $key);
} else { } else {
$result = $resultSet; $result = $resultSet;
} }
@@ -1335,8 +1281,8 @@ abstract class PDOConnection extends Connection
// 判断占位符 // 判断占位符
$sql = is_numeric($key) ? $sql = is_numeric($key) ?
substr_replace($sql, $value, strpos($sql, '?'), 1) : substr_replace($sql, $value, strpos($sql, '?'), 1) :
substr_replace($sql, $value, strpos($sql, ':' . $key), strlen(':' . $key)); substr_replace($sql, $value, strpos($sql, ':' . $key), strlen(':' . $key));
} }
return rtrim($sql); return rtrim($sql);
@@ -1595,16 +1541,17 @@ abstract class PDOConnection extends Connection
* @access public * @access public
* @param BaseQuery $query 查询对象 * @param BaseQuery $query 查询对象
* @param array $sqlArray SQL批处理指令 * @param array $sqlArray SQL批处理指令
* @param array $bind 参数绑定
* @return bool * @return bool
*/ */
public function batchQuery(BaseQuery $query, array $sqlArray = []): bool public function batchQuery(BaseQuery $query, array $sqlArray = [], array $bind = []): bool
{ {
// 自动启动事务支持 // 自动启动事务支持
$this->startTrans(); $this->startTrans();
try { try {
foreach ($sqlArray as $sql) { foreach ($sqlArray as $sql) {
$this->pdoExecute($query, $sql); $this->pdoExecute($query, $sql, $bind);
} }
// 提交事务 // 提交事务
$this->commit(); $this->commit();
@@ -1697,7 +1644,7 @@ abstract class PDOConnection extends Connection
$pk = $query->getAutoInc(); $pk = $query->getAutoInc();
if ($pk) { if ($pk) {
$type = $this->getFieldsBind($query->getTable())[$pk]; $type = $this->getFieldBindType($pk);
if (PDO::PARAM_INT == $type) { if (PDO::PARAM_INT == $type) {
$insertId = (int) $insertId; $insertId = (int) $insertId;
@@ -1811,17 +1758,6 @@ abstract class PDOConnection extends Connection
return $this->connect($dbConfig, $r, $r == $m ? false : $dbMaster); return $this->connect($dbConfig, $r, $r == $m ? false : $dbMaster);
} }
/**
* 获取数据库的唯一标识
* @access public
* @param string $suffix 标识后缀
* @return string
*/
public function getUniqueXid(string $suffix = ''): string
{
return $this->config['hostname'] . '_' . $this->config['database'] . $suffix;
}
/** /**
* 执行数据库Xa事务 * 执行数据库Xa事务
* @access public * @access public
@@ -1847,7 +1783,7 @@ abstract class PDOConnection extends Connection
$dbs[$key] = $db; $dbs[$key] = $db;
} }
$db->startTransXa($db->getUniqueXid('_' . $xid) ); $db->startTransXa($xid);
} }
try { try {
@@ -1857,17 +1793,17 @@ abstract class PDOConnection extends Connection
} }
foreach ($dbs as $db) { foreach ($dbs as $db) {
$db->prepareXa($db->getUniqueXid('_' . $xid)); $db->prepareXa($xid);
} }
foreach ($dbs as $db) { foreach ($dbs as $db) {
$db->commitXa($db->getUniqueXid('_' . $xid) ); $db->commitXa($xid);
} }
return $result; return $result;
} catch (\Exception | \Throwable $e) { } catch (\Exception | \Throwable $e) {
foreach ($dbs as $db) { foreach ($dbs as $db) {
$db->rollbackXa($db->getUniqueXid('_' . $xid) ); $db->rollbackXa($xid);
} }
throw $e; throw $e;
} }
@@ -1880,8 +1816,7 @@ abstract class PDOConnection extends Connection
* @return void * @return void
*/ */
public function startTransXa(string $xid): void public function startTransXa(string $xid): void
{ {}
}
/** /**
* 预编译XA事务 * 预编译XA事务
@@ -1890,8 +1825,7 @@ abstract class PDOConnection extends Connection
* @return void * @return void
*/ */
public function prepareXa(string $xid): void public function prepareXa(string $xid): void
{ {}
}
/** /**
* 提交XA事务 * 提交XA事务
@@ -1900,8 +1834,7 @@ abstract class PDOConnection extends Connection
* @return void * @return void
*/ */
public function commitXa(string $xid): void public function commitXa(string $xid): void
{ {}
}
/** /**
* 回滚XA事务 * 回滚XA事务
@@ -1910,6 +1843,5 @@ abstract class PDOConnection extends Connection
* @return void * @return void
*/ */
public function rollbackXa(string $xid): void public function rollbackXa(string $xid): void
{ {}
}
} }

View File

@@ -13,6 +13,7 @@ declare (strict_types = 1);
namespace think\db; namespace think\db;
use PDOStatement; use PDOStatement;
use think\helper\Str;
/** /**
* PDO数据查询类 * PDO数据查询类

View File

@@ -111,6 +111,8 @@ class Mongo
$result[$item] = $val; $result[$item] = $val;
} elseif (isset($val[0]) && 'exp' == $val[0]) { } elseif (isset($val[0]) && 'exp' == $val[0]) {
$result[$item] = $val[1]; $result[$item] = $val[1];
} elseif (is_null($val)) {
$result[$item] = 'NULL';
} else { } else {
$result[$item] = $this->parseValue($query, $val, $key); $result[$item] = $this->parseValue($query, $val, $key);
} }

View File

@@ -12,7 +12,6 @@ declare (strict_types = 1);
namespace think\db\builder; namespace think\db\builder;
use PDO;
use think\db\Builder; use think\db\Builder;
use think\db\exception\DbException as Exception; use think\db\exception\DbException as Exception;
use think\db\Query; use think\db\Query;
@@ -28,7 +27,7 @@ class Mysql extends Builder
* @var array * @var array
*/ */
protected $parser = [ protected $parser = [
'parseCompare' => ['=', '!=', '<>', '>', '>=', '<', '<='], 'parseCompare' => ['=', '<>', '>', '>=', '<', '<='],
'parseLike' => ['LIKE', 'NOT LIKE'], 'parseLike' => ['LIKE', 'NOT LIKE'],
'parseBetween' => ['NOT BETWEEN', 'BETWEEN'], 'parseBetween' => ['NOT BETWEEN', 'BETWEEN'],
'parseIn' => ['NOT IN', 'IN'], 'parseIn' => ['NOT IN', 'IN'],
@@ -102,8 +101,7 @@ class Mysql extends Builder
$this->parseComment($query, $options['comment']), $this->parseComment($query, $options['comment']),
$this->parseForce($query, $options['force']), $this->parseForce($query, $options['force']),
], ],
$this->selectSql $this->selectSql);
);
} }
/** /**
@@ -138,8 +136,7 @@ class Mysql extends Builder
$this->parseDuplicate($query, $options['duplicate']), $this->parseDuplicate($query, $options['duplicate']),
$this->parseComment($query, $options['comment']), $this->parseComment($query, $options['comment']),
], ],
$this->insertSql $this->insertSql);
);
} }
/** /**
@@ -147,9 +144,10 @@ class Mysql extends Builder
* @access public * @access public
* @param Query $query 查询对象 * @param Query $query 查询对象
* @param array $dataSet 数据集 * @param array $dataSet 数据集
* @param bool $replace 是否replace
* @return string * @return string
*/ */
public function insertAll(Query $query, array $dataSet): string public function insertAll(Query $query, array $dataSet, bool $replace = false): string
{ {
$options = $query->getOptions(); $options = $query->getOptions();
@@ -183,7 +181,7 @@ class Mysql extends Builder
return str_replace( return str_replace(
['%INSERT%', '%EXTRA%', '%TABLE%', '%PARTITION%', '%FIELD%', '%DATA%', '%DUPLICATE%', '%COMMENT%'], ['%INSERT%', '%EXTRA%', '%TABLE%', '%PARTITION%', '%FIELD%', '%DATA%', '%DUPLICATE%', '%COMMENT%'],
[ [
!empty($options['replace']) ? 'REPLACE' : 'INSERT', $replace ? 'REPLACE' : 'INSERT',
$this->parseExtra($query, $options['extra']), $this->parseExtra($query, $options['extra']),
$this->parseTable($query, $options['table']), $this->parseTable($query, $options['table']),
$this->parsePartition($query, $options['partition']), $this->parsePartition($query, $options['partition']),
@@ -192,56 +190,7 @@ class Mysql extends Builder
$this->parseDuplicate($query, $options['duplicate']), $this->parseDuplicate($query, $options['duplicate']),
$this->parseComment($query, $options['comment']), $this->parseComment($query, $options['comment']),
], ],
$this->insertAllSql $this->insertAllSql);
);
}
/**
* 生成insertall SQL
* @access public
* @param Query $query 查询对象
* @param array $keys 键值
* @param array $values 数据
* @return string
*/
public function insertAllByKeys(Query $query, array $keys, array $datas): string
{
$options = $query->getOptions();
// 获取绑定信息
$bind = $query->getFieldsBindType();
$fields = [];
$values = [];
foreach ($keys as $field) {
$fields[] = $this->parseKey($query, $field);
}
foreach ($datas as $data) {
foreach ($data as $key => &$val) {
if (!$query->isAutoBind()) {
$val = PDO::PARAM_STR == $bind[$keys[$key]] ? '\'' . $val . '\'' : $val;
} else {
$val = $this->parseDataBind($query, $keys[$key], $val, $bind);
}
}
$values[] = '( ' . implode(',', $data) . ' )';
}
return str_replace(
['%INSERT%', '%EXTRA%', '%TABLE%', '%PARTITION%', '%FIELD%', '%DATA%', '%DUPLICATE%', '%COMMENT%'],
[
!empty($options['replace']) ? 'REPLACE' : 'INSERT',
$this->parseExtra($query, $options['extra']),
$this->parseTable($query, $options['table']),
$this->parsePartition($query, $options['partition']),
implode(' , ', $fields),
implode(' , ', $values),
$this->parseDuplicate($query, $options['duplicate']),
$this->parseComment($query, $options['comment']),
],
$this->insertAllSql
);
} }
/** /**
@@ -259,10 +208,9 @@ class Mysql extends Builder
if (empty($data)) { if (empty($data)) {
return ''; return '';
} }
$set = []; $set = [];
foreach ($data as $key => $val) { foreach ($data as $key => $val) {
$set[] = (strpos($key, '->') ? strstr($key, '->', true) : $key) . ' = ' . $val; $set[] = $key . ' = ' . $val;
} }
return str_replace( return str_replace(
@@ -279,8 +227,7 @@ class Mysql extends Builder
$this->parseLock($query, $options['lock']), $this->parseLock($query, $options['lock']),
$this->parseComment($query, $options['comment']), $this->parseComment($query, $options['comment']),
], ],
$this->updateSql $this->updateSql);
);
} }
/** /**
@@ -307,8 +254,7 @@ class Mysql extends Builder
$this->parseLock($query, $options['lock']), $this->parseLock($query, $options['lock']),
$this->parseComment($query, $options['comment']), $this->parseComment($query, $options['comment']),
], ],
$this->deleteSql $this->deleteSql);
);
} }
/** /**

View File

@@ -49,21 +49,12 @@ trait AggregateQuery
} }
$options = $this->getOptions(); $options = $this->getOptions();
if (isset($options['cache'])) { $subSql = $this->options($options)
$cache = $options['cache'];
unset($options['cache']);
}
$subSql = $this->options($options)
->field('count(' . $field . ') AS think_count') ->field('count(' . $field . ') AS think_count')
->bind($this->bind) ->bind($this->bind)
->buildSql(); ->buildSql();
$query = $this->newQuery(); $query = $this->newQuery()->table([$subSql => '_group_count_']);
if (isset($cache)) {
$query->setOption('cache', $cache);
}
$query->table([$subSql => '_group_count_']);
$count = $query->aggregate('COUNT', '*'); $count = $query->aggregate('COUNT', '*');
} else { } else {

View File

@@ -13,6 +13,7 @@ declare (strict_types = 1);
namespace think\db\concern; namespace think\db\concern;
use think\db\Raw; use think\db\Raw;
use think\helper\Str;
/** /**
* JOIN和VIEW查询 * JOIN和VIEW查询

View File

@@ -559,4 +559,23 @@ trait ModelRelationQuery
$result->refreshOrigin(); $result->refreshOrigin();
} }
/**
* 查询软删除数据
* @access public
* @return Query
*/
public function withTrashed()
{
return $this->model ? $this->model->queryWithTrashed() : $this;
}
/**
* 只查询软删除数据
* @access public
* @return Query
*/
public function onlyTrashed()
{
return $this->model ? $this->model->queryOnlyTrashed() : $this;
}
} }

View File

@@ -64,33 +64,6 @@ trait ParamsBind
return isset($this->bind[$key]); return isset($this->bind[$key]);
} }
/**
* 设置自动参数绑定
* @access public
* @param bool $bind 是否自动参数绑定
* @return $this
*/
public function autoBind(bool $bind)
{
$this->options['auto_bind'] = $bind;
return $this;
}
/**
* 检测是否开启自动参数绑定
* @access public
* @return bool
*/
public function isAutoBind(): bool
{
$autoBind = $this->getConfig('auto_param_bind');
if (null !== $this->getOptions('auto_bind')) {
$autoBind = $this->getOptions('auto_bind');
}
return (bool) $autoBind;
}
/** /**
* 参数绑定 * 参数绑定
* @access public * @access public

View File

@@ -455,15 +455,18 @@ trait WhereQuery
*/ */
protected function parseArrayWhereItems(array $field, string $logic) protected function parseArrayWhereItems(array $field, string $logic)
{ {
$where = []; if (key($field) !== 0) {
foreach ($field as $key => $val) { $where = [];
if (is_int($key)) { foreach ($field as $key => $val) {
$where[] = $val; if ($val instanceof Raw) {
} elseif ($val instanceof Raw) { $where[] = [$key, 'exp', $val];
$where[] = [$key, 'exp', $val]; } else {
} else { $where[] = is_null($val) ? [$key, 'NULL', ''] : [$key, is_array($val) ? 'IN' : '=', $val];
$where[] = is_null($val) ? [$key, 'NULL', ''] : [$key, is_array($val) ? 'IN' : '=', $val]; }
} }
} else {
// 数组批量查询
$where = $field;
} }
if (!empty($where)) { if (!empty($where)) {

View File

@@ -258,7 +258,7 @@ class Mongo extends Connection
$this->queryStartTime = microtime(true); $this->queryStartTime = microtime(true);
if ($session = $this->getSession()) { if ($session = $this->getSession()) {
$this->cursor = $this->mongo->executeQuery($namespace, $mongoQuery, [ $this->cursor = $this->mongo->executeQuery($namespace, $query, [
'readPreference' => is_null($readPreference) ? new ReadPreference(ReadPreference::RP_PRIMARY) : $readPreference, 'readPreference' => is_null($readPreference) ? new ReadPreference(ReadPreference::RP_PRIMARY) : $readPreference,
'session' => $session, 'session' => $session,
]); ]);

View File

@@ -60,7 +60,7 @@ class Sqlsrv extends PDOConnection
public function getFields(string $tableName): array public function getFields(string $tableName): array
{ {
[$tableName] = explode(' ', $tableName); [$tableName] = explode(' ', $tableName);
strpos($tableName, '.') && $tableName = substr($tableName, strpos($tableName, '.') + 1); strpos($tableName,'.') && $tableName = substr($tableName,strpos($tableName,'.') + 1);
$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
JOIN information_schema.columns AS c JOIN information_schema.columns AS c

View File

@@ -67,6 +67,12 @@ abstract class Relation
*/ */
protected $selfRelation = false; protected $selfRelation = false;
/**
* 关联数据数量限制
* @var int
*/
protected $withLimit;
/** /**
* 关联数据字段限制 * 关联数据字段限制
* @var array * @var array
@@ -194,6 +200,18 @@ abstract class Relation
} }
} }
/**
* 限制关联数据的数量
* @access public
* @param int $limit 关联数量限制
* @return $this
*/
public function withLimit(int $limit)
{
$this->withLimit = $limit;
return $this;
}
/** /**
* 限制关联数据的字段 * 限制关联数据的字段
* @access public * @access public
@@ -226,18 +244,6 @@ abstract class Relation
return $this; return $this;
} }
/**
* 限制关联数据的数量
* @access public
* @param int $limit 关联数量限制
* @return $this
*/
public function withLimit(int $limit)
{
$this->query->limit($limit);
return $this;
}
/** /**
* 设置关联数据不存在的时候默认值 * 设置关联数据不存在的时候默认值
* @access public * @access public
@@ -275,15 +281,14 @@ abstract class Relation
* @access protected * @access protected
* @return mixed * @return mixed
*/ */
protected function getClosureType(Closure $closure, $query = null) protected function getClosureType(Closure $closure)
{ {
$reflect = new ReflectionFunction($closure); $reflect = new ReflectionFunction($closure);
$params = $reflect->getParameters(); $params = $reflect->getParameters();
if (!empty($params)) { if (!empty($params)) {
$type = $params[0]->getType(); $type = $params[0]->getType();
$query = $query ?: $this->query; return is_null($type) || Relation::class == $type->getName() ? $this : $this->query;
return is_null($type) || Relation::class == $type->getName() ? $this : $query;
} }
return $this; return $this;

View File

@@ -15,6 +15,7 @@ namespace think\model\concern;
use InvalidArgumentException; use InvalidArgumentException;
use think\db\Raw; use think\db\Raw;
use think\helper\Str; use think\helper\Str;
use think\Model;
use think\model\Relation; use think\model\Relation;
/** /**
@@ -382,9 +383,7 @@ trait Attribute
} elseif (isset($this->type[$name])) { } elseif (isset($this->type[$name])) {
// 类型转换 // 类型转换
$value = $this->writeTransform($value, $this->type[$name]); $value = $this->writeTransform($value, $this->type[$name]);
} elseif ($this->isRelationAttr($name)) { } elseif (array_key_exists($name, $this->origin) && is_object($value) && method_exists($value, '__toString')) {
$this->relation[$name] = $value;
} elseif ((array_key_exists($name, $this->origin) || empty($this->origin)) && is_object($value) && method_exists($value, '__toString')) {
// 对象类型 // 对象类型
$value = $value->__toString(); $value = $value->__toString();
} }
@@ -447,7 +446,6 @@ trait Attribute
break; break;
case 'array': case 'array':
$value = (array) $value; $value = (array) $value;
// no break
case 'json': case 'json':
$option = !empty($param) ? (int) $param : JSON_UNESCAPED_UNICODE; $option = !empty($param) ? (int) $param : JSON_UNESCAPED_UNICODE;
$value = json_encode($value, $option); $value = json_encode($value, $option);

View File

@@ -204,55 +204,52 @@ trait Conversion
*/ */
public function toArray(): array public function toArray(): array
{ {
$item = $visible = $hidden = []; $item = [];
$hasVisible = false; $hasVisible = false;
foreach ($this->visible as $key => $val) { foreach ($this->visible as $key => $val) {
if (is_string($val)) { if (is_string($val)) {
if (strpos($val, '.')) { if (strpos($val, '.')) {
[$relation, $name] = explode('.', $val); [$relation, $name] = explode('.', $val);
$visible[$relation][] = $name; $this->visible[$relation][] = $name;
} else { } else {
$visible[$val] = true; $this->visible[$val] = true;
$hasVisible = true; $hasVisible = true;
} }
unset($this->visible[$key]);
} }
} }
foreach ($this->hidden as $key => $val) { foreach ($this->hidden as $key => $val) {
if (is_string($val)) { if (is_string($val)) {
if (strpos($val, '.')) { if (strpos($val, '.')) {
[$relation, $name] = explode('.', $val); [$relation, $name] = explode('.', $val);
$hidden[$relation][] = $name; $this->hidden[$relation][] = $name;
} else { } else {
$hidden[$val] = true; $this->hidden[$val] = true;
} }
unset($this->hidden[$key]);
} }
} }
// 追加属性(必须定义获取器)
foreach ($this->append as $key => $name) {
$this->appendAttrToArray($item, $key, $name, $visible, $hidden);
}
// 合并关联数据 // 合并关联数据
$data = array_merge($this->data, $this->relation); $data = array_merge($this->data, $this->relation);
foreach ($data as $key => $val) { foreach ($data as $key => $val) {
if ($val instanceof Model || $val instanceof ModelCollection) { if ($val instanceof Model || $val instanceof ModelCollection) {
// 关联模型对象 // 关联模型对象
if (isset($visible[$key]) && is_array($visible[$key])) { if (isset($this->visible[$key]) && is_array($this->visible[$key])) {
$val->visible($visible[$key]); $val->visible($this->visible[$key]);
} elseif (isset($hidden[$key]) && is_array($hidden[$key])) { } elseif (isset($this->hidden[$key]) && is_array($this->hidden[$key])) {
$val->hidden($hidden[$key], true); $val->hidden($this->hidden[$key]);
} }
// 关联模型对象 // 关联模型对象
if (!isset($hidden[$key]) || true !== $hidden[$key]) { if (!isset($this->hidden[$key]) || true !== $this->hidden[$key]) {
$item[$key] = $val->toArray(); $item[$key] = $val->toArray();
} }
} elseif (isset($visible[$key])) { } elseif (isset($this->visible[$key])) {
$item[$key] = $this->getAttr($key); $item[$key] = $this->getAttr($key);
} elseif (!isset($hidden[$key]) && !$hasVisible) { } elseif (!isset($this->hidden[$key]) && !$hasVisible) {
$item[$key] = $this->getAttr($key); $item[$key] = $this->getAttr($key);
} }
@@ -264,6 +261,11 @@ trait Conversion
} }
} }
// 追加属性(必须定义获取器)
foreach ($this->append as $key => $name) {
$this->appendAttrToArray($item, $key, $name);
}
if ($this->convertNameToCamel) { if ($this->convertNameToCamel) {
foreach ($item as $key => $val) { foreach ($item as $key => $val) {
$name = Str::camel($key); $name = Str::camel($key);
@@ -277,38 +279,27 @@ trait Conversion
return $item; return $item;
} }
protected function appendAttrToArray(array &$item, $key, $name, array $visible, array $hidden) protected function appendAttrToArray(array &$item, $key, $name)
{ {
if (is_array($name)) { if (is_array($name)) {
// 批量追加关联对象属性 // 追加关联对象属性
$relation = $this->getRelationWith($key, $hidden, $visible); $relation = $this->getRelation($key, true);
$item[$key] = $relation ? $relation->append($name)->toArray() : []; $item[$key] = $relation ? $relation->append($name)
->toArray() : [];
} elseif (strpos($name, '.')) { } elseif (strpos($name, '.')) {
// 追加单个关联对象属性 [$key, $attr] = explode('.', $name);
[$key, $attr] = explode('.', $name); // 追加关联对象属性
$relation = $this->getRelationWith($key, $hidden, $visible); $relation = $this->getRelation($key, true);
$item[$key] = $relation ? $relation->append([$attr])->toArray() : []; $item[$key] = $relation ? $relation->append([$attr])
->toArray() : [];
} else { } else {
$value = $this->getAttr($name); $value = $this->getAttr($name);
$item[$name] = $value; $item[$name] = $value;
$this->getBindAttrValue($name, $value, $item); $this->getBindAttrValue($name, $value, $item);
} }
} }
protected function getRelationWith(string $key, array $hidden, array $visible)
{
$relation = $this->getRelation($key, true);
if ($relation) {
if (isset($visible[$key])) {
$relation->visible($visible[$key]);
} elseif (isset($hidden[$key])) {
$relation->hidden($hidden[$key]);
}
}
return $relation;
}
protected function getBindAttrValue(string $name, $value, array &$item = []) protected function getBindAttrValue(string $name, $value, array &$item = [])
{ {
$relation = $this->isRelationAttr($name); $relation = $this->isRelationAttr($name);

View File

@@ -346,7 +346,7 @@ trait RelationShip
*/ */
public function bindAttr(string $relation, array $attrs = []) public function bindAttr(string $relation, array $attrs = [])
{ {
$relation = $this->getRelation($relation, true); $relation = $this->getRelation($relation);
foreach ($attrs as $key => $attr) { foreach ($attrs as $key => $attr) {
$key = is_numeric($key) ? $attr : $key; $key = is_numeric($key) ? $attr : $key;
@@ -735,9 +735,7 @@ trait RelationShip
protected function getRelationData(Relation $modelRelation) protected function getRelationData(Relation $modelRelation)
{ {
if ($this->parent && !$modelRelation->isSelfRelation() if ($this->parent && !$modelRelation->isSelfRelation()
&& get_class($this->parent) == get_class($modelRelation->getModel()) && get_class($this->parent) == get_class($modelRelation->getModel())) {
&& $modelRelation instanceof OneToOne
) {
return $this->parent; return $this->parent;
} }

View File

@@ -18,18 +18,14 @@ use think\Model;
/** /**
* 数据软删除 * 数据软删除
* @mixin Model * @mixin Model
* @method $this withTrashed()
* @method $this onlyTrashed()
*/ */
trait SoftDelete trait SoftDelete
{ {
/**
public function db($scope = []): Query * 是否包含软删除数据
{ * @var bool
$query = parent::db($scope); */
$this->withNoTrashed($query); protected $withTrashed = false;
return $query;
}
/** /**
* 判断当前实例是否被软删除 * 判断当前实例是否被软删除
@@ -47,18 +43,74 @@ trait SoftDelete
return false; return false;
} }
public function scopeWithTrashed(Query $query) /**
* 查询软删除数据
* @access public
* @return Query
*/
public static function withTrashed(): Query
{ {
$query->removeOption('soft_delete'); $model = new static();
return $model->withTrashedData(true)->db();
} }
public function scopeOnlyTrashed(Query $query) /**
* 查询软删除数据
* @access public
* @return Query
*/
public function queryWithTrashed(): Query
{
return $this->withTrashedData(true)->db();
}
/**
* 是否包含软删除数据
* @access protected
* @param bool $withTrashed 是否包含软删除数据
* @return $this
*/
protected function withTrashedData(bool $withTrashed)
{
$this->withTrashed = $withTrashed;
return $this;
}
/**
* 只查询软删除数据
* @access public
* @return Query
*/
public static function onlyTrashed(): Query
{
$model = new static();
$field = $model->getDeleteTimeField(true);
if ($field) {
return $model
->db()
->useSoftDelete($field, $model->getWithTrashedExp());
}
return $model->db();
}
/**
* 只查询软删除数据
* @access public
* @return Query
*/
public function queryOnlyTrashed(): Query
{ {
$field = $this->getDeleteTimeField(true); $field = $this->getDeleteTimeField(true);
if ($field) { if ($field) {
$query->useSoftDelete($field, $this->getWithTrashedExp()); return $this->db()
->useSoftDelete($field, $this->getWithTrashedExp());
} }
return $this->db();
} }
/** /**
@@ -87,9 +139,9 @@ trait SoftDelete
if ($name && !$force) { if ($name && !$force) {
// 软删除 // 软删除
$this->set($name, $this->autoWriteTimestamp()); $this->set($name, $this->autoWriteTimestamp($name));
$this->exists()->withEvent(false)->save(); $result = $this->exists()->withEvent(false)->save();
$this->withEvent(true); $this->withEvent(true);
} else { } else {
@@ -97,7 +149,7 @@ trait SoftDelete
$where = $this->getWhere(); $where = $this->getWhere();
// 删除当前模型数据 // 删除当前模型数据
$this->db() $result = $this->db()
->where($where) ->where($where)
->removeOption('soft_delete') ->removeOption('soft_delete')
->delete(); ->delete();
@@ -120,8 +172,8 @@ trait SoftDelete
/** /**
* 删除记录 * 删除记录
* @access public * @access public
* @param mixed $data 主键列表 支持闭包查询条件 * @param mixed $data 主键列表 支持闭包查询条件
* @param bool $force 是否强制删除 * @param bool $force 是否强制删除
* @return bool * @return bool
*/ */
public static function destroy($data, bool $force = false): bool public static function destroy($data, bool $force = false): bool
@@ -130,20 +182,18 @@ trait SoftDelete
if (empty($data) && 0 !== $data) { if (empty($data) && 0 !== $data) {
return false; return false;
} }
$model = (new static());
$query = $model->db(false);
// 仅当强制删除时包含软删除数据 // 仅当强制删除时包含软删除数据
$model = (new static());
if ($force) { if ($force) {
$query->removeOption('soft_delete'); $model->withTrashedData(true);
} }
$query = $model->db(false);
if (is_array($data) && key($data) !== 0) { if (is_array($data) && key($data) !== 0) {
$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 false; return false;
@@ -152,7 +202,6 @@ trait SoftDelete
$resultSet = $query->select($data); $resultSet = $query->select($data);
foreach ($resultSet as $result) { foreach ($resultSet as $result) {
/** @var Model $result */
$result->force($force)->delete(); $result->force($force)->delete();
} }
@@ -162,7 +211,7 @@ trait SoftDelete
/** /**
* 恢复被软删除的记录 * 恢复被软删除的记录
* @access public * @access public
* @param array $where 更新条件 * @param array $where 更新条件
* @return bool * @return bool
*/ */
public function restore($where = []): bool public function restore($where = []): bool
@@ -194,7 +243,7 @@ trait SoftDelete
/** /**
* 获取软删除字段 * 获取软删除字段
* @access protected * @access protected
* @param bool $read 是否查询操作 写操作的时候会自动去掉表别名 * @param bool $read 是否查询操作 写操作的时候会自动去掉表别名
* @return string|false * @return string|false
*/ */
protected function getDeleteTimeField(bool $read = false) protected function getDeleteTimeField(bool $read = false)
@@ -220,7 +269,7 @@ trait SoftDelete
/** /**
* 查询的时候默认排除软删除数据 * 查询的时候默认排除软删除数据
* @access protected * @access protected
* @param Query $query * @param Query $query
* @return void * @return void
*/ */
protected function withNoTrashed(Query $query): void protected function withNoTrashed(Query $query): void

View File

@@ -179,7 +179,7 @@ trait TimeStamp
protected function formatDateTime($format, $time = 'now', bool $timestamp = false) protected function formatDateTime($format, $time = 'now', bool $timestamp = false)
{ {
if (empty($time)) { if (empty($time)) {
return $time; return;
} }
if (false === $format) { if (false === $format) {

View File

@@ -14,6 +14,7 @@ namespace think\model\relation;
use Closure; use Closure;
use think\db\BaseQuery as Query; use think\db\BaseQuery as Query;
use think\helper\Str;
use think\Model; use think\Model;
/** /**
@@ -240,7 +241,7 @@ class BelongsTo extends OneToOne
if (!empty($this->bindAttr)) { if (!empty($this->bindAttr)) {
// 绑定关联属性 // 绑定关联属性
$this->bindAttr($result, $relationModel); $this->bindAttr($result, $relationModel);
$result->hidden([$relation], true); $result->hidden([$relation]);
} }
} }
} }
@@ -282,7 +283,7 @@ class BelongsTo extends OneToOne
if (!empty($this->bindAttr)) { if (!empty($this->bindAttr)) {
// 绑定关联属性 // 绑定关联属性
$this->bindAttr($result, $relationModel); $this->bindAttr($result, $relationModel);
$result->hidden([$relation], true); $result->hidden([$relation]);
} }
} }

View File

@@ -346,11 +346,6 @@ class BelongsToMany extends Relation
$closure($this->getClosureType($closure)); $closure($this->getClosureType($closure));
} }
$withLimit = $this->query->getOptions('limit');
if ($withLimit) {
$this->query->removeOption('limit');
}
// 预载入关联查询 支持嵌套预载入 // 预载入关联查询 支持嵌套预载入
$list = $this->belongsToManyQuery($this->foreignKey, $this->localKey, $where) $list = $this->belongsToManyQuery($this->foreignKey, $this->localKey, $where)
->with($subRelation) ->with($subRelation)
@@ -358,12 +353,12 @@ class BelongsToMany extends Relation
->select(); ->select();
// 组装模型数据 // 组装模型数据
$data = []; $data = [];
foreach ($list as $set) { foreach ($list as $set) {
$pivot = $this->matchPivot($set); $pivot = $this->matchPivot($set);
$key = $pivot[$this->localKey]; $key = $pivot[$this->localKey];
if ($withLimit && isset($data[$key]) && count($data[$key]) >= $withLimit) { if ($this->withLimit && isset($data[$key]) && count($data[$key]) >= $this->withLimit) {
continue; continue;
} }
@@ -394,6 +389,10 @@ class BelongsToMany extends Relation
$fields = $this->getQueryFields($tableName); $fields = $this->getQueryFields($tableName);
if ($this->withLimit) {
$this->query->limit($this->withLimit);
}
$this->query $this->query
->field($fields) ->field($fields)
->tableField(true, $table, 'pivot', 'pivot__') ->tableField(true, $table, 'pivot', 'pivot__')

View File

@@ -15,6 +15,7 @@ namespace think\model\relation;
use Closure; use Closure;
use think\Collection; use think\Collection;
use think\db\BaseQuery as Query; use think\db\BaseQuery as Query;
use think\helper\Str;
use think\Model; use think\Model;
use think\model\Relation; use think\model\Relation;
@@ -57,6 +58,10 @@ class HasMany extends Relation
$closure($this->getClosureType($closure)); $closure($this->getClosureType($closure));
} }
if ($this->withLimit) {
$this->query->limit($this->withLimit);
}
return $this->query return $this->query
->where($this->foreignKey, $this->parent->{$this->localKey}) ->where($this->foreignKey, $this->parent->{$this->localKey})
->relation($subRelation) ->relation($subRelation)
@@ -205,11 +210,6 @@ class HasMany extends Relation
$this->query->withoutField($this->withoutField); $this->query->withoutField($this->withoutField);
} }
$withLimit = $this->query->getOptions('limit');
if ($withLimit) {
$this->query->removeOption('limit');
}
$list = $this->query $list = $this->query
->where($where) ->where($where)
->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null) ->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null)
@@ -217,12 +217,12 @@ class HasMany extends Relation
->select(); ->select();
// 组装模型数据 // 组装模型数据
$data = []; $data = [];
foreach ($list as $set) { foreach ($list as $set) {
$key = $set->$foreignKey; $key = $set->$foreignKey;
if ($withLimit && isset($data[$key]) && count($data[$key]) >= $withLimit) { if ($this->withLimit && isset($data[$key]) && count($data[$key]) >= $this->withLimit) {
continue; continue;
} }
@@ -241,10 +241,6 @@ class HasMany extends Relation
*/ */
public function save($data, bool $replace = true) public function save($data, bool $replace = true)
{ {
if ($data instanceof Model) {
$data = $data->getData();
}
$model = $this->make(); $model = $this->make();
return $model->replace($replace)->save($data) ? $model : false; return $model->replace($replace)->save($data) ? $model : false;
@@ -264,7 +260,7 @@ class HasMany extends Relation
// 保存关联表数据 // 保存关联表数据
$data[$this->foreignKey] = $this->parent->{$this->localKey}; $data[$this->foreignKey] = $this->parent->{$this->localKey};
return (new $this->model($data))->setSuffix($this->getModel()->getSuffix()); return new $this->model($data);
} }
/** /**

View File

@@ -79,6 +79,10 @@ class HasManyThrough extends Relation
$this->baseQuery(); $this->baseQuery();
if ($this->withLimit) {
$this->query->limit($this->withLimit);
}
return $this->query->relation($subRelation) return $this->query->relation($subRelation)
->select() ->select()
->setParent(clone $this->parent); ->setParent(clone $this->parent);
@@ -260,24 +264,19 @@ class HasManyThrough extends Relation
$throughKey = Str::snake(class_basename($this->model)) . "." . $this->throughKey; $throughKey = Str::snake(class_basename($this->model)) . "." . $this->throughKey;
} }
$withLimit = $this->query->getOptions('limit');
if ($withLimit) {
$this->query->removeOption('limit');
}
$list = $this->query $list = $this->query
->where($throughKey, 'in', $keys) ->where($throughKey, 'in', $keys)
->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null) ->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null)
->select(); ->select();
// 组装模型数据 // 组装模型数据
$data = []; $data = [];
$keys = $throughList->column($this->foreignKey, $this->throughPk); $keys = $throughList->column($this->foreignKey, $this->throughPk);
foreach ($list as $set) { foreach ($list as $set) {
$key = $keys[$set->{$this->throughKey}]; $key = $keys[$set->{$this->throughKey}];
if ($withLimit && isset($data[$key]) && count($data[$key]) >= $withLimit) { if ($this->withLimit && isset($data[$key]) && count($data[$key]) >= $this->withLimit) {
continue; continue;
} }

View File

@@ -14,6 +14,7 @@ namespace think\model\relation;
use Closure; use Closure;
use think\db\BaseQuery as Query; use think\db\BaseQuery as Query;
use think\helper\Str;
use think\Model; use think\Model;
/** /**
@@ -239,7 +240,7 @@ class HasOne extends OneToOne
if (!empty($this->bindAttr)) { if (!empty($this->bindAttr)) {
// 绑定关联属性 // 绑定关联属性
$this->bindAttr($result, $relationModel); $this->bindAttr($result, $relationModel);
$result->hidden([$relation], true); $result->hidden([$relation]);
} }
} }
} }
@@ -281,7 +282,7 @@ class HasOne extends OneToOne
if (!empty($this->bindAttr)) { if (!empty($this->bindAttr)) {
// 绑定关联属性 // 绑定关联属性
$this->bindAttr($result, $relationModel); $this->bindAttr($result, $relationModel);
$result->hidden([$relation], true); $result->hidden([$relation]);
} }
} }

View File

@@ -12,6 +12,7 @@
namespace think\model\relation; namespace think\model\relation;
use Closure; use Closure;
use think\helper\Str;
use think\Model; use think\Model;
/** /**
@@ -151,10 +152,14 @@ class HasOneThrough extends HasManyThrough
->select(); ->select();
// 组装模型数据 // 组装模型数据
return array_map(function ($key) use ($list) { $data = [];
$set = $list->where($this->throughKey, '=', $key)->first(); $keys = array_flip($keys);
return $set ? clone $set : null;
}, $keys); foreach ($list as $set) {
$data[$keys[$set->{$this->throughKey}]] = $set;
}
return $data;
} }
} }

View File

@@ -15,6 +15,7 @@ use Closure;
use think\Collection; use think\Collection;
use think\db\BaseQuery as Query; use think\db\BaseQuery as Query;
use think\db\exception\DbException as Exception; use think\db\exception\DbException as Exception;
use think\helper\Str;
use think\Model; use think\Model;
use think\model\Relation; use think\model\Relation;
@@ -76,6 +77,10 @@ class MorphMany extends Relation
$this->baseQuery(); $this->baseQuery();
if ($this->withLimit) {
$this->query->limit($this->withLimit);
}
return $this->query->relation($subRelation) return $this->query->relation($subRelation)
->select() ->select()
->setParent(clone $this->parent); ->setParent(clone $this->parent);
@@ -253,11 +258,6 @@ class MorphMany extends Relation
$closure($this->getClosureType($closure)); $closure($this->getClosureType($closure));
} }
$withLimit = $this->query->getOptions('limit');
if ($withLimit) {
$this->query->removeOption('limit');
}
$list = $this->query $list = $this->query
->where($where) ->where($where)
->with($subRelation) ->with($subRelation)
@@ -266,11 +266,11 @@ class MorphMany extends Relation
$morphKey = $this->morphKey; $morphKey = $this->morphKey;
// 组装模型数据 // 组装模型数据
$data = []; $data = [];
foreach ($list as $set) { foreach ($list as $set) {
$key = $set->$morphKey; $key = $set->$morphKey;
if ($withLimit && isset($data[$key]) && count($data[$key]) >= $withLimit) { if ($this->withLimit && isset($data[$key]) && count($data[$key]) >= $this->withLimit) {
continue; continue;
} }
@@ -289,10 +289,6 @@ class MorphMany extends Relation
*/ */
public function save($data, bool $replace = true) public function save($data, bool $replace = true)
{ {
if ($data instanceof Model) {
$data = $data->getData();
}
$model = $this->make(); $model = $this->make();
return $model->replace($replace)->save($data) ? $model : false; return $model->replace($replace)->save($data) ? $model : false;
@@ -315,7 +311,7 @@ class MorphMany extends Relation
$data[$this->morphKey] = $this->parent->$pk; $data[$this->morphKey] = $this->parent->$pk;
$data[$this->morphType] = $this->type; $data[$this->morphType] = $this->type;
return (new $this->model($data))->setSuffix($this->getModel()->getSuffix()); return new $this->model($data);
} }
/** /**

View File

@@ -14,6 +14,7 @@ namespace think\model\relation;
use Closure; use Closure;
use think\db\BaseQuery as Query; use think\db\BaseQuery as Query;
use think\db\exception\DbException as Exception; use think\db\exception\DbException as Exception;
use think\helper\Str;
use think\Model; use think\Model;
use think\model\Relation; use think\model\Relation;
@@ -259,10 +260,6 @@ class MorphOne extends Relation
*/ */
public function save($data, bool $replace = true) public function save($data, bool $replace = true)
{ {
if ($data instanceof Model) {
$data = $data->getData();
}
$model = $this->make(); $model = $this->make();
return $model->replace($replace)->save($data) ? $model : false; return $model->replace($replace)->save($data) ? $model : false;
} }
@@ -284,7 +281,7 @@ class MorphOne extends Relation
$data[$this->morphKey] = $this->parent->$pk; $data[$this->morphKey] = $this->parent->$pk;
$data[$this->morphType] = $this->type; $data[$this->morphType] = $this->type;
return (new $this->model($data))->setSuffix($this->getModel()->getSuffix()); return new $this->model($data);
} }
/** /**

View File

@@ -13,7 +13,6 @@ namespace think\model\relation;
use Closure; use Closure;
use think\db\exception\DbException as Exception; use think\db\exception\DbException as Exception;
use think\db\Query;
use think\helper\Str; use think\helper\Str;
use think\Model; use think\Model;
use think\model\Relation; use think\model\Relation;
@@ -47,16 +46,14 @@ class MorphTo extends Relation
*/ */
protected $relation; protected $relation;
protected $queryCaller = [];
/** /**
* 架构函数 * 架构函数
* @access public * @access public
* @param Model $parent 上级模型对象 * @param Model $parent 上级模型对象
* @param string $morphType 多态字段名 * @param string $morphType 多态字段名
* @param string $morphKey 外键名 * @param string $morphKey 外键名
* @param array $alias 多态别名定义 * @param array $alias 多态别名定义
* @param ?string $relation 关联名 * @param string $relation 关联名
*/ */
public function __construct(Model $parent, string $morphType, string $morphKey, array $alias = [], string $relation = null) public function __construct(Model $parent, string $morphType, string $morphKey, array $alias = [], string $relation = null)
{ {
@@ -83,8 +80,8 @@ class MorphTo extends Relation
/** /**
* 延迟获取关联数据 * 延迟获取关联数据
* @access public * @access public
* @param array $subRelation 子关联名 * @param array $subRelation 子关联名
* @param ?Closure $closure 闭包查询条件 * @param Closure $closure 闭包查询条件
* @return Model * @return Model
*/ */
public function getRelation(array $subRelation = [], Closure $closure = null) public function getRelation(array $subRelation = [], Closure $closure = null)
@@ -98,7 +95,7 @@ class MorphTo extends Relation
// 主键数据 // 主键数据
$pk = $this->parent->$morphKey; $pk = $this->parent->$morphKey;
$relationModel = $this->buildQuery((new $model)->relation($subRelation))->find($pk); $relationModel = (new $model)->relation($subRelation)->find($pk);
if ($relationModel) { if ($relationModel) {
$relationModel->setParent(clone $this->parent); $relationModel->setParent(clone $this->parent);
@@ -110,11 +107,11 @@ class MorphTo extends Relation
/** /**
* 根据关联条件查询当前模型 * 根据关联条件查询当前模型
* @access public * @access public
* @param string $operator 比较操作符 * @param string $operator 比较操作符
* @param integer $count 个数 * @param integer $count 个数
* @param string $id 关联表的统计字段 * @param string $id 关联表的统计字段
* @param string $joinType JOIN类型 * @param string $joinType JOIN类型
* @param Query $query Query对象 * @param Query $query Query对象
* @return Query * @return Query
*/ */
public function has(string $operator = '>=', int $count = 1, string $id = '*', string $joinType = '', Query $query = null) public function has(string $operator = '>=', int $count = 1, string $id = '*', string $joinType = '', Query $query = null)
@@ -125,46 +122,22 @@ class MorphTo extends Relation
/** /**
* 根据关联条件查询当前模型 * 根据关联条件查询当前模型
* @access public * @access public
* @param mixed $where 查询条件(数组或者闭包) * @param mixed $where 查询条件(数组或者闭包)
* @param mixed $fields 字段 * @param mixed $fields 字段
* @param string $joinType JOIN类型 * @param string $joinType JOIN类型
* @param ?Query $query Query对象 * @param Query $query Query对象
* @return Query * @return Query
*/ */
public function hasWhere($where = [], $fields = null, string $joinType = '', Query $query = null) public function hasWhere($where = [], $fields = null, string $joinType = '', Query $query = null)
{ {
$alias = class_basename($this->parent); throw new Exception('relation not support: hasWhere');
$types = $this->parent->distinct()->column($this->morphType);
$query = $query ?: $this->parent->db();
return $query->alias($alias)
->where(function (Query $query) use ($types, $where, $alias) {
foreach ($types as $type) {
if ($type) {
$query->whereExists(function (Query $query) use ($type, $where, $alias) {
$class = $this->parseModel($type);
/** @var Model $model */
$model = new $class();
$table = $model->getTable();
$query
->table($table)
->where($alias . '.' . $this->morphType, $type)
->whereRaw("`{$alias}`.`{$this->morphKey}`=`{$table}`.`{$model->getPk()}`")
->where($where);
}, 'OR');
}
}
});
} }
/** /**
* 解析模型的完整命名空间 * 解析模型的完整命名空间
* @access protected * @access protected
* @param string $model 模型名(或者完整类名) * @param string $model 模型名(或者完整类名)
* @return Model * @return string
*/ */
protected function parseModel(string $model): string protected function parseModel(string $model): string
{ {
@@ -185,7 +158,7 @@ class MorphTo extends Relation
/** /**
* 设置多态别名 * 设置多态别名
* @access public * @access public
* @param array $alias 别名定义 * @param array $alias 别名定义
* @return $this * @return $this
*/ */
public function setAlias(array $alias) public function setAlias(array $alias)
@@ -200,7 +173,7 @@ class MorphTo extends Relation
* @access public * @access public
* @return $this * @return $this
*/ */
public function removeOption(string $option = '') public function removeOption()
{ {
return $this; return $this;
} }
@@ -208,11 +181,11 @@ class MorphTo extends Relation
/** /**
* 预载入关联查询 * 预载入关联查询
* @access public * @access public
* @param array $resultSet 数据集 * @param array $resultSet 数据集
* @param string $relation 当前关联名 * @param string $relation 当前关联名
* @param array $subRelation 子关联名 * @param array $subRelation 子关联名
* @param ?Closure $closure 闭包 * @param Closure $closure 闭包
* @param array $cache 关联缓存 * @param array $cache 关联缓存
* @return void * @return void
* @throws Exception * @throws Exception
*/ */
@@ -238,8 +211,8 @@ class MorphTo extends Relation
if (!\is_null($closure)) { if (!\is_null($closure)) {
$obj = $closure($obj); $obj = $closure($obj);
} }
$pk = $obj->getPk(); $pk = $obj->getPk();
$list = $obj->with($subRelation) $list = $obj->with($subRelation)
->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null) ->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null)
->select($val); ->select($val);
$data = []; $data = [];
@@ -269,11 +242,11 @@ class MorphTo extends Relation
/** /**
* 预载入关联查询 * 预载入关联查询
* @access public * @access public
* @param Model $result 数据对象 * @param Model $result 数据对象
* @param string $relation 当前关联名 * @param string $relation 当前关联名
* @param array $subRelation 子关联名 * @param array $subRelation 子关联名
* @param ?Closure $closure 闭包 * @param Closure $closure 闭包
* @param array $cache 关联缓存 * @param array $cache 关联缓存
* @return void * @return void
*/ */
public function eagerlyResult(Model $result, string $relation, array $subRelation = [], Closure $closure = null, array $cache = []): void public function eagerlyResult(Model $result, string $relation, array $subRelation = [], Closure $closure = null, array $cache = []): void
@@ -287,42 +260,36 @@ class MorphTo extends Relation
/** /**
* 关联统计 * 关联统计
* @access public * @access public
* @param Model $result 数据对象 * @param Model $result 数据对象
* @param ?Closure $closure 闭包 * @param Closure $closure 闭包
* @param string $aggregate 聚合查询方法 * @param string $aggregate 聚合查询方法
* @param string $field 字段 * @param string $field 字段
* @return integer * @return integer
*/ */
public function relationCount(Model $result, Closure $closure = null, string $aggregate = 'count', string $field = '*') public function relationCount(Model $result, Closure $closure = null, string $aggregate = 'count', string $field = '*')
{ {}
}
/** /**
* 多态MorphTo 关联模型预查询 * 多态MorphTo 关联模型预查询
* @access protected * @access protected
* @param string $model 关联模型对象 * @param string $model 关联模型对象
* @param string $relation 关联名 * @param string $relation 关联名
* @param Model $result * @param Model $result
* @param array $subRelation 子关联 * @param array $subRelation 子关联
* @param array $cache 关联缓存 * @param array $cache 关联缓存
* @return void * @return void
*/ */
protected function eagerlyMorphToOne(string $model, string $relation, Model $result, array $subRelation = [], array $cache = []): void protected function eagerlyMorphToOne(string $model, string $relation, Model $result, array $subRelation = [], array $cache = []): void
{ {
// 预载入关联查询 支持嵌套预载入 // 预载入关联查询 支持嵌套预载入
$pk = $this->parent->{$this->morphKey}; $pk = $this->parent->{$this->morphKey};
$data = (new $model)->with($subRelation)
->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null)
->find($pk);
$data = null; if ($data) {
$data->setParent(clone $result);
if (\class_exists($model)) { $data->exists(true);
$data = (new $model)->with($subRelation)
->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null)
->find($pk);
if ($data) {
$data->setParent(clone $result);
$data->exists(true);
}
} }
$result->setRelation($relation, $data ?: null); $result->setRelation($relation, $data ?: null);
@@ -331,8 +298,8 @@ class MorphTo extends Relation
/** /**
* 添加关联数据 * 添加关联数据
* @access public * @access public
* @param Model $model 关联模型对象 * @param Model $model 关联模型对象
* @param string $type 多态类型 * @param string $type 多态类型
* @return Model * @return Model
*/ */
public function associate(Model $model, string $type = ''): Model public function associate(Model $model, string $type = ''): Model
@@ -365,18 +332,4 @@ class MorphTo extends Relation
return $this->parent->setRelation($this->relation, null); return $this->parent->setRelation($this->relation, null);
} }
protected function buildQuery(Query $query)
{
foreach ($this->queryCaller as $caller) {
call_user_func_array([$query, $caller[0]], $caller[1]);
}
return $query;
}
public function __call($method, $args)
{
$this->queryCaller[] = [$method, $args];
return $this;
}
} }

View File

@@ -216,7 +216,12 @@ class MorphToMany extends BelongsToMany
} }
$fields = $this->getQueryFields($tableName); $fields = $this->getQueryFields($tableName);
$query = $this->query
if ($this->withLimit) {
$this->query->limit($this->withLimit);
}
$query = $this->query
->field($fields) ->field($fields)
->tableField(true, $table, 'pivot', 'pivot__'); ->tableField(true, $table, 'pivot', 'pivot__');
@@ -244,11 +249,6 @@ class MorphToMany extends BelongsToMany
$closure($this->getClosureType($closure)); $closure($this->getClosureType($closure));
} }
$withLimit = $this->query->getOptions('limit');
if ($withLimit) {
$this->query->removeOption('limit');
}
// 预载入关联查询 支持嵌套预载入 // 预载入关联查询 支持嵌套预载入
$list = $this->belongsToManyQuery($this->foreignKey, $this->localKey, $where) $list = $this->belongsToManyQuery($this->foreignKey, $this->localKey, $where)
->with($subRelation) ->with($subRelation)
@@ -256,7 +256,7 @@ class MorphToMany extends BelongsToMany
->select(); ->select();
// 组装模型数据 // 组装模型数据
$data = []; $data = [];
foreach ($list as $set) { foreach ($list as $set) {
$pivot = []; $pivot = [];
foreach ($set->getData() as $key => $val) { foreach ($set->getData() as $key => $val) {
@@ -271,7 +271,7 @@ class MorphToMany extends BelongsToMany
$key = $pivot[$this->localKey]; $key = $pivot[$this->localKey];
if ($withLimit && isset($data[$key]) && count($data[$key]) >= $withLimit) { if ($this->withLimit && isset($data[$key]) && count($data[$key]) >= $this->withLimit) {
continue; continue;
} }
@@ -300,10 +300,10 @@ class MorphToMany extends BelongsToMany
$model = new $this->model; $model = new $this->model;
$id = $model->insertGetId($data); $id = $model->insertGetId($data);
} }
} elseif (is_numeric($data) || is_string($data)) { } else if (is_numeric($data) || is_string($data)) {
// 根据关联表主键直接写入中间表 // 根据关联表主键直接写入中间表
$id = $data; $id = $data;
} elseif ($data instanceof Model) { } else if ($data instanceof Model) {
// 根据关联表主键直接写入中间表 // 根据关联表主键直接写入中间表
$id = $data->getKey(); $id = $data->getKey();
} }
@@ -371,10 +371,10 @@ class MorphToMany extends BelongsToMany
{ {
if (is_array($data)) { if (is_array($data)) {
$id = $data; $id = $data;
} elseif (is_numeric($data) || is_string($data)) { } else if (is_numeric($data) || is_string($data)) {
// 根据关联表主键直接写入中间表 // 根据关联表主键直接写入中间表
$id = $data; $id = $data;
} elseif ($data instanceof Model) { } else if ($data instanceof Model) {
// 根据关联表主键直接写入中间表 // 根据关联表主键直接写入中间表
$id = $data->getKey(); $id = $data->getKey();
} }
@@ -441,7 +441,7 @@ class MorphToMany extends BelongsToMany
if (!in_array($id, $current)) { if (!in_array($id, $current)) {
$this->attach($id, $attributes); $this->attach($id, $attributes);
$changes['attached'][] = $id; $changes['attached'][] = $id;
} elseif (count($attributes) > 0 && $this->attach($id, $attributes)) { } else if (count($attributes) > 0 && $this->attach($id, $attributes)) {
$changes['updated'][] = $id; $changes['updated'][] = $id;
} }
} }
@@ -481,7 +481,7 @@ class MorphToMany extends BelongsToMany
{ {
if (is_array($map)) { if (is_array($map)) {
static::$morphMap = $merge && static::$morphMap static::$morphMap = $merge && static::$morphMap
? $map + static::$morphMap : $map; ? $map + static::$morphMap : $map;
} }
return static::$morphMap; return static::$morphMap;

View File

@@ -91,28 +91,14 @@ abstract class OneToOne extends Relation
$query->via($joinAlias); $query->via($joinAlias);
if ($this instanceof BelongsTo) { if ($this instanceof BelongsTo) {
$joinOn = $name . '.' . $this->foreignKey . '=' . $joinAlias . '.' . $this->localKey;
$foreignKeyExp = $this->foreignKey;
if (strpos($foreignKeyExp, '.') === false) {
$foreignKeyExp = $name . '.' . $this->foreignKey;
}
$joinOn = $foreignKeyExp . '=' . $joinAlias . '.' . $this->localKey;
} else { } else {
$joinOn = $name . '.' . $this->localKey . '=' . $joinAlias . '.' . $this->foreignKey;
$foreignKeyExp = $this->foreignKey;
if (strpos($foreignKeyExp, '.') === false) {
$foreignKeyExp = $joinAlias . '.' . $this->foreignKey;
}
$joinOn = $name . '.' . $this->localKey . '=' . $foreignKeyExp;
} }
if ($closure) { if ($closure) {
// 执行闭包查询 // 执行闭包查询
$closure($this->getClosureType($closure, $query)); $closure($this->getClosureType($closure));
// 使用withField指定获取关联的字段 // 使用withField指定获取关联的字段
if ($this->withField) { if ($this->withField) {
@@ -201,10 +187,6 @@ abstract class OneToOne extends Relation
*/ */
public function save($data, bool $replace = true) public function save($data, bool $replace = true)
{ {
if ($data instanceof Model) {
$data = $data->getData();
}
$model = $this->make(); $model = $this->make();
return $model->replace($replace)->save($data) ? $model : false; return $model->replace($replace)->save($data) ? $model : false;
@@ -224,9 +206,10 @@ abstract class OneToOne extends Relation
// 保存关联表数据 // 保存关联表数据
$data[$this->foreignKey] = $this->parent->{$this->localKey}; $data[$this->foreignKey] = $this->parent->{$this->localKey};
return (new $this->model($data))->setSuffix($this->getModel()->getSuffix()); return new $this->model($data);
} }
/** /**
* 绑定关联表的属性到父模型属性 * 绑定关联表的属性到父模型属性
* @access public * @access public

View File

@@ -21,11 +21,12 @@
"think\\test\\queue\\": "tests" "think\\test\\queue\\": "tests"
} }
}, },
"minimum-stability": "dev",
"require": { "require": {
"ext-json": "*", "ext-json": "*",
"topthink/framework": "^6.0 || ^8.0", "topthink/framework": "^6.0",
"symfony/process": ">=4.2", "symfony/process": "^4.2",
"nesbot/carbon": ">=2.16" "nesbot/carbon": "^2.16"
}, },
"extra": { "extra": {
"think": { "think": {
@@ -33,13 +34,13 @@
"think\\queue\\Service" "think\\queue\\Service"
], ],
"config": { "config": {
"queue": "src/config/queue.php" "queue": "src/config.php"
} }
} }
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.2", "phpunit/phpunit": "^6.2",
"mockery/mockery": "^1.2", "mockery/mockery": "^1.2",
"topthink/think-migration": "^3.0" "topthink/think-migration": "^3.0.0"
} }
} }

View File

@@ -0,0 +1,39 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
return [
'default' => 'sync',
'connections' => [
'sync' => [
'type' => 'sync',
],
'database' => [
'type' => 'database',
'queue' => 'default',
'table' => 'jobs',
'connection' => null,
],
'redis' => [
'type' => 'redis',
'queue' => 'default',
'host' => '127.0.0.1',
'port' => 6379,
'password' => '',
'select' => 0,
'timeout' => 0,
'persistent' => false,
],
],
'failed' => [
'type' => 'none',
'table' => 'failed_jobs',
],
];

View File

@@ -13,6 +13,6 @@ class Queue extends Facade
{ {
protected static function getFacadeClass() protected static function getFacadeClass()
{ {
return 'queue'; return \think\Queue::class;
} }
} }

View File

@@ -26,7 +26,7 @@ class CallQueuedHandler
{ {
$command = unserialize($data['command']); $command = unserialize($data['command']);
$this->app->invoke([$command, 'handle'], [$job]); $this->app->invoke([$command, 'handle']);
if (!$job->isDeletedOrReleased()) { if (!$job->isDeletedOrReleased()) {
$job->delete(); $job->delete();

View File

@@ -194,11 +194,23 @@ abstract class Job
*/ */
protected function resolve($name, $param) protected function resolve($name, $param)
{ {
$namespace = $this->app->getNamespace() . '\\job\\'; // $namespace = $this->app->getNamespace() . '\\job\\';
////
//// $class = false !== strpos($name, '\\') ? $name : $namespace . Str::studly($name);
////
//// return $this->app->make($class, [$param], true);
if (strpos($name, '\\') === false) {
$class = false !== strpos($name, '\\') ? $name : $namespace . Str::studly($name); if (strpos($name, '/') === false) {
$app = '';
} else {
list($app, $name) = explode('/', $name, 2);
}
return $this->app->make($class, [$param], true); $name = ($this->app->config->get('app.app_namespace') ?: 'app\\') . ($app ? strtolower($app) . '\\' : '') . 'job\\' . $name;
}
return $this->app->make($name, [$param], true);
} }
public function getResolvedJob() public function getResolvedJob()

View File

@@ -52,7 +52,7 @@ class Worker
*/ */
public $paused = false; public $paused = false;
public function __construct(Queue $queue, Event $event, Handle $handle, ?Cache $cache = null) public function __construct(Queue $queue, Event $event, Handle $handle, Cache $cache = null)
{ {
$this->queue = $queue; $this->queue = $queue;
$this->event = $event; $this->event = $event;

View File

@@ -245,7 +245,7 @@ class Template
// 页面缓存 // 页面缓存
ob_start(); ob_start();
if (version_compare(PHP_VERSION, '8.0', '>=')) { if (PHP_VERSION > 8.0) {
ob_implicit_flush(false); ob_implicit_flush(false);
} else { } else {
ob_implicit_flush(0); ob_implicit_flush(0);
@@ -1074,9 +1074,6 @@ class Template
switch (strtolower($fun)) { switch (strtolower($fun)) {
case 'raw': case 'raw':
break; break;
case 'htmlentities':
$name = 'htmlentities((string) ' . $name . ')';
break;
case 'date': case 'date':
$name = 'date(' . $args[1] . ',!is_numeric(' . $name . ')? strtotime(' . $name . ') : ' . $name . ')'; $name = 'date(' . $args[1] . ',!is_numeric(' . $name . ')? strtotime(' . $name . ') : ' . $name . ')';
break; break;

View File

@@ -13,8 +13,7 @@ namespace think\facade;
if (class_exists('think\Facade')) { if (class_exists('think\Facade')) {
class Facade extends \think\Facade class Facade extends \think\Facade
{ {}
}
} else { } else {
class Facade class Facade
{ {
@@ -32,8 +31,7 @@ if (class_exists('think\Facade')) {
* @return string * @return string
*/ */
protected static function getFacadeClass() protected static function getFacadeClass()
{ {}
}
/** /**
* 创建Facade实例 * 创建Facade实例
@@ -54,6 +52,7 @@ if (class_exists('think\Facade')) {
} }
return self::$instance; return self::$instance;
} }
// 调用实际类的方法 // 调用实际类的方法