fix(vendor): 修复依赖升级导致的不兼容问题
This commit is contained in:
@@ -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');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
168
src/vendor/topthink/think-helper/src/Collection.php
vendored
168
src/vendor/topthink/think-helper/src/Collection.php
vendored
@@ -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
|
||||||
*/
|
*/
|
||||||
|
|||||||
68
src/vendor/topthink/think-helper/src/helper.php
vendored
68
src/vendor/topthink/think-helper/src/helper.php
vendored
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
29
src/vendor/topthink/think-orm/src/DbManager.php
vendored
29
src/vendor/topthink/think-orm/src/DbManager.php
vendored
@@ -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
|
||||||
|
|||||||
38
src/vendor/topthink/think-orm/src/Model.php
vendored
38
src/vendor/topthink/think-orm/src/Model.php
vendored
@@ -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)) {
|
||||||
|
|||||||
13
src/vendor/topthink/think-orm/src/Paginator.php
vendored
13
src/vendor/topthink/think-orm/src/Paginator.php
vendored
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
92
src/vendor/topthink/think-orm/src/db/Builder.php
vendored
92
src/vendor/topthink/think-orm/src/db/Builder.php
vendored
@@ -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);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ declare (strict_types = 1);
|
|||||||
namespace think\db;
|
namespace think\db;
|
||||||
|
|
||||||
use PDOStatement;
|
use PDOStatement;
|
||||||
|
use think\helper\Str;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PDO数据查询类
|
* PDO数据查询类
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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查询
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
@@ -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,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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__')
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
11
src/vendor/topthink/think-queue/composer.json
vendored
11
src/vendor/topthink/think-queue/composer.json
vendored
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
39
src/vendor/topthink/think-queue/src/config.php
vendored
Normal file
39
src/vendor/topthink/think-queue/src/config.php
vendored
Normal 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',
|
||||||
|
],
|
||||||
|
];
|
||||||
@@ -13,6 +13,6 @@ class Queue extends Facade
|
|||||||
{
|
{
|
||||||
protected static function getFacadeClass()
|
protected static function getFacadeClass()
|
||||||
{
|
{
|
||||||
return 'queue';
|
return \think\Queue::class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调用实际类的方法
|
// 调用实际类的方法
|
||||||
|
|||||||
Reference in New Issue
Block a user