提交的内容
This commit is contained in:
32
vendor/topthink/think-orm/src/db/BaseBuilder.php
vendored
Executable file → Normal file
32
vendor/topthink/think-orm/src/db/BaseBuilder.php
vendored
Executable file → Normal file
@ -9,13 +9,15 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db;
|
||||
|
||||
use BackedEnum;
|
||||
use Closure;
|
||||
use think\db\BaseQuery as Query;
|
||||
use think\db\exception\DbException as Exception;
|
||||
use UnitEnum;
|
||||
|
||||
/**
|
||||
* Db Base Builder.
|
||||
@ -94,7 +96,7 @@ abstract class BaseBuilder
|
||||
*
|
||||
* @param ConnectionInterface $connection 数据库连接对象实例
|
||||
*/
|
||||
public function __construct(ConnectionInterface $connection)
|
||||
public function __construct(?ConnectionInterface $connection)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
}
|
||||
@ -157,7 +159,7 @@ abstract class BaseBuilder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function parseKey(Query $query, string|int|Raw $key, bool $strict = false): string;
|
||||
abstract public function parseKey(Query $query, string | int | Raw $key, bool $strict = false): string;
|
||||
|
||||
/**
|
||||
* 查询额外参数分析.
|
||||
@ -187,7 +189,7 @@ abstract class BaseBuilder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function parseTable(Query $query, array|string $tables): string;
|
||||
abstract protected function parseTable(Query $query, array | string $tables): string;
|
||||
|
||||
/**
|
||||
* where分析.
|
||||
@ -273,7 +275,7 @@ abstract class BaseBuilder
|
||||
$where[] = $this->parseFieldsAnd($query, $value, $field, $logic, $binds);
|
||||
} else {
|
||||
// 对字段使用表达式查询
|
||||
$field = is_string($field) ? $field : '';
|
||||
$field = is_string($field) ? $field : '';
|
||||
$where[] = ' ' . $logic . ' ' . $this->parseWhereItem($query, $field, $value, $binds);
|
||||
}
|
||||
}
|
||||
@ -466,7 +468,7 @@ abstract class BaseBuilder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function parseBetween(Query $query, string $key, string $exp, array|string $value, $field, int $bindType): string;
|
||||
abstract protected function parseBetween(Query $query, string $key, string $exp, array | string $value, $field, int $bindType): string;
|
||||
|
||||
/**
|
||||
* Exists查询.
|
||||
@ -480,7 +482,7 @@ abstract class BaseBuilder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function parseExists(Query $query, string $key, string $exp, Raw|Closure $value, string $field, int $bindType): string
|
||||
protected function parseExists(Query $query, string $key, string $exp, Raw | Closure $value, string $field, int $bindType): string
|
||||
{
|
||||
// EXISTS 查询
|
||||
if ($value instanceof Closure) {
|
||||
@ -532,6 +534,10 @@ abstract class BaseBuilder
|
||||
$value = $this->parseClosure($query, $value);
|
||||
} elseif ($value instanceof Raw) {
|
||||
$value = $this->parseRaw($query, $value);
|
||||
} elseif ($value instanceof BackedEnum) {
|
||||
$value = $value->value;
|
||||
} elseif ($value instanceof UnitEnum) {
|
||||
$value = $value->name;
|
||||
}
|
||||
|
||||
if ('=' == $exp && is_null($value)) {
|
||||
@ -560,9 +566,9 @@ abstract class BaseBuilder
|
||||
}
|
||||
|
||||
return $key . ' ' . substr($exp, 0, -4)
|
||||
. $this->parseDateTime($query, $value[0], $field, $bindType)
|
||||
. ' AND '
|
||||
. $this->parseDateTime($query, $value[1], $field, $bindType);
|
||||
. $this->parseDateTime($query, $value[0], $field, $bindType)
|
||||
. ' AND '
|
||||
. $this->parseDateTime($query, $value[1], $field, $bindType);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -665,7 +671,7 @@ abstract class BaseBuilder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function parseGroup(Query $query, string|array $group): string;
|
||||
abstract protected function parseGroup(Query $query, string | array $group): string;
|
||||
|
||||
/**
|
||||
* having分析.
|
||||
@ -740,7 +746,7 @@ abstract class BaseBuilder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function parseForce(Query $query, string|array $index): string;
|
||||
abstract protected function parseForce(Query $query, string | array $index): string;
|
||||
|
||||
/**
|
||||
* 设置锁机制.
|
||||
@ -750,7 +756,7 @@ abstract class BaseBuilder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function parseLock(Query $query, bool|string $lock = false): string;
|
||||
abstract protected function parseLock(Query $query, bool | string $lock = false): string;
|
||||
|
||||
/**
|
||||
* 生成查询SQL.
|
||||
|
||||
331
vendor/topthink/think-orm/src/db/BaseQuery.php
vendored
Executable file → Normal file
331
vendor/topthink/think-orm/src/db/BaseQuery.php
vendored
Executable file → Normal file
@ -9,7 +9,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db;
|
||||
|
||||
@ -70,6 +70,13 @@ abstract class BaseQuery
|
||||
*/
|
||||
protected $prefix = '';
|
||||
|
||||
/**
|
||||
* 当前数据表后缀
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $suffix = '';
|
||||
|
||||
/**
|
||||
* 当前查询参数.
|
||||
*
|
||||
@ -84,8 +91,8 @@ abstract class BaseQuery
|
||||
*/
|
||||
public function __construct(ConnectionInterface $connection)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
$this->prefix = $this->connection->getConfig('prefix');
|
||||
$this->connection = $connection;
|
||||
$this->prefix = $this->connection->getConfig('prefix');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,10 +137,8 @@ abstract class BaseQuery
|
||||
|
||||
if ($this->model && method_exists($this->model, 'scope' . $method)) {
|
||||
// 动态调用命名范围
|
||||
$method = 'scope' . $method;
|
||||
array_unshift($args, $this);
|
||||
|
||||
call_user_func_array([$this->model, $method], $args);
|
||||
$this->options['scope'][$method] = [[$this->model, 'scope' . $method], $args];
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -157,7 +162,7 @@ abstract class BaseQuery
|
||||
if (isset($this->options['table'])) {
|
||||
$query->table($this->options['table']);
|
||||
} else {
|
||||
$query->name($this->name);
|
||||
$query->name($this->name)->suffix($this->suffix);
|
||||
}
|
||||
|
||||
if (!empty($this->options['json'])) {
|
||||
@ -172,6 +177,10 @@ abstract class BaseQuery
|
||||
$query->lazyFields($this->options['lazy_fields']);
|
||||
}
|
||||
|
||||
if (isset($this->options['alias'])) {
|
||||
$query->alias($this->options['alias']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
@ -199,6 +208,20 @@ abstract class BaseQuery
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定当前数据表后缀.
|
||||
*
|
||||
* @param string $suffix 后缀
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function suffix(string $suffix)
|
||||
{
|
||||
$this->suffix = $suffix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前的数据表名称.
|
||||
*
|
||||
@ -258,20 +281,21 @@ abstract class BaseQuery
|
||||
|
||||
/**
|
||||
* 得到当前或者指定名称的数据表.
|
||||
* @param bool $alias 是否返回数据表别名
|
||||
*
|
||||
* @param string $name 不含前缀的数据表名字
|
||||
*
|
||||
* @return mixed
|
||||
* @return string|array|Raw
|
||||
*/
|
||||
public function getTable(string $name = '')
|
||||
public function getTable(bool $alias = false)
|
||||
{
|
||||
if (empty($name) && isset($this->options['table'])) {
|
||||
return $this->options['table'];
|
||||
if (isset($this->options['table'])) {
|
||||
$table = $this->options['table'];
|
||||
if ($alias && is_string($table) && !empty($this->options['alias'][$table])) {
|
||||
return $this->options['alias'][$table];
|
||||
}
|
||||
return $table;
|
||||
}
|
||||
|
||||
$name = $name ?: $this->name;
|
||||
|
||||
return $this->prefix . Str::snake($name);
|
||||
return $this->prefix . Str::snake($this->name) . $this->suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -288,6 +312,20 @@ abstract class BaseQuery
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置只读字段.
|
||||
*
|
||||
* @param array $fields 只读字段
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function readonly(array $fields)
|
||||
{
|
||||
$this->options['readonly_fields'] = $fields;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最近一次查询的sql语句.
|
||||
*
|
||||
@ -311,11 +349,11 @@ abstract class BaseQuery
|
||||
/**
|
||||
* 获取最近插入的ID.
|
||||
*
|
||||
* @param string $sequence 自增序列名
|
||||
* @param string|null $sequence 自增序列名
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLastInsID(string $sequence = null)
|
||||
public function getLastInsID(?string $sequence = null)
|
||||
{
|
||||
return $this->connection->getLastInsID($this, $sequence);
|
||||
}
|
||||
@ -325,36 +363,98 @@ abstract class BaseQuery
|
||||
*
|
||||
* @param string $field 字段名
|
||||
* @param mixed $default 默认值
|
||||
* @param bool $useModelAttr 是否使用模型获取器
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function value(string $field, $default = null)
|
||||
public function value(string $field, $default = null, bool $useModelAttr = false)
|
||||
{
|
||||
$result = $this->connection->value($this, $field, $default);
|
||||
|
||||
$array[$field] = $result;
|
||||
$this->result($array);
|
||||
if ($this->model && $useModelAttr) {
|
||||
// JSON数据处理
|
||||
if (!empty($this->options['json'])) {
|
||||
$this->jsonModelResult($array);
|
||||
}
|
||||
return $this->model->newInstance($array)->getAttr($field);
|
||||
}
|
||||
|
||||
if (!empty($this->options['json'])) {
|
||||
$this->jsonResult($array);
|
||||
}
|
||||
return $array[$field];
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到某个字段的值 并且经过模型的获取器处理
|
||||
*
|
||||
* @param string $field 字段名
|
||||
* @param mixed $default 默认值
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function valueWithAttr(string $field, $default = null)
|
||||
{
|
||||
return $this->value($field, $default, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到某个列的数组.
|
||||
*
|
||||
* @param string|array $field 字段名 多个字段用逗号分隔
|
||||
* @param string $key 索引
|
||||
* @param bool $useModelAttr 是否使用模型获取器
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function column(string|array $field, string $key = ''): array
|
||||
public function column(string | array $field, string $key = '', bool $useModelAttr = false): array
|
||||
{
|
||||
$result = $this->connection->column($this, $field, $key);
|
||||
return array_map(function ($item) use ($field, $useModelAttr) {
|
||||
if (is_array($item)) {
|
||||
if ($this->model && $useModelAttr) {
|
||||
// JSON数据处理
|
||||
if (!empty($this->options['json'])) {
|
||||
$this->jsonModelResult($item);
|
||||
}
|
||||
return $this->model->newInstance($item)->toArray();
|
||||
}
|
||||
if (!empty($this->options['json'])) {
|
||||
$this->jsonResult($item);
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
if (count($result) != count($result, 1)) {
|
||||
$this->resultSet($result, false);
|
||||
}
|
||||
if (is_array($field) && 1 === count($field)) {
|
||||
$field = current($field);
|
||||
}
|
||||
|
||||
return $result;
|
||||
$array[$field] = $item;
|
||||
if ($this->model && $useModelAttr) {
|
||||
if (!empty($this->options['json'])) {
|
||||
$this->jsonModelResult($array);
|
||||
}
|
||||
return $this->model->newInstance($array)->getAttr($field);
|
||||
}
|
||||
if (!empty($this->options['json'])) {
|
||||
$this->jsonResult($array);
|
||||
}
|
||||
return $array[$field];
|
||||
}, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到某个列的数组 并且经过模型的获取器处理.
|
||||
*
|
||||
* @param string|array $field 字段名 多个字段用逗号分隔
|
||||
* @param string $key 索引
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function columnWithAttr(string | array $field, string $key = '')
|
||||
{
|
||||
return $this->column($field, $key, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -365,7 +465,7 @@ abstract class BaseQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function union(string|array|Closure $union, bool $all = false)
|
||||
public function union(string | array | Closure $union, bool $all = false)
|
||||
{
|
||||
$this->options['union']['type'] = $all ? 'UNION ALL' : 'UNION';
|
||||
|
||||
@ -385,7 +485,7 @@ abstract class BaseQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function unionAll(string|array|Closure $union)
|
||||
public function unionAll(string | array | Closure $union)
|
||||
{
|
||||
return $this->union($union, true);
|
||||
}
|
||||
@ -397,7 +497,7 @@ abstract class BaseQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function field(string|array|Raw|bool $field)
|
||||
public function field(string | array | Raw | bool $field)
|
||||
{
|
||||
if (empty($field)) {
|
||||
return $this;
|
||||
@ -437,7 +537,7 @@ abstract class BaseQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withoutField(array|string $field)
|
||||
public function withoutField(array | string $field)
|
||||
{
|
||||
if (empty($field)) {
|
||||
return $this;
|
||||
@ -470,7 +570,7 @@ abstract class BaseQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function tableField(string|array|bool $field, string $tableName, string $prefix = '', string $alias = '')
|
||||
public function tableField(string | array | bool $field, string $tableName, string $prefix = '', string $alias = '')
|
||||
{
|
||||
if (empty($field)) {
|
||||
return $this;
|
||||
@ -530,8 +630,8 @@ abstract class BaseQuery
|
||||
public function removeOption(string $option = '')
|
||||
{
|
||||
if ('' === $option) {
|
||||
$this->options = [];
|
||||
$this->bind = [];
|
||||
$this->options = [];
|
||||
$this->bind = [];
|
||||
} elseif (isset($this->options[$option])) {
|
||||
unset($this->options[$option]);
|
||||
}
|
||||
@ -542,12 +642,12 @@ abstract class BaseQuery
|
||||
/**
|
||||
* 指定查询数量.
|
||||
*
|
||||
* @param int $offset 起始位置
|
||||
* @param int $length 查询数量
|
||||
* @param int $offset 起始位置
|
||||
* @param int|null $length 查询数量
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function limit(int $offset, int $length = null)
|
||||
public function limit(int $offset, ?int $length = null)
|
||||
{
|
||||
$this->options['limit'] = $offset . ($length ? ',' . $length : '');
|
||||
|
||||
@ -557,12 +657,12 @@ abstract class BaseQuery
|
||||
/**
|
||||
* 指定分页.
|
||||
*
|
||||
* @param int $page 页数
|
||||
* @param int $listRows 每页数量
|
||||
* @param int $page 页数
|
||||
* @param int|null $listRows 每页数量
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function page(int $page, int $listRows = null)
|
||||
public function page(int $page, ?int $listRows = null)
|
||||
{
|
||||
$this->options['page'] = [$page, $listRows];
|
||||
|
||||
@ -576,7 +676,7 @@ abstract class BaseQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function table(string|array|Raw $table)
|
||||
public function table(string | array | Raw $table)
|
||||
{
|
||||
if (is_string($table) && !str_contains($table, ')')) {
|
||||
$table = $this->tableStr($table);
|
||||
@ -595,20 +695,20 @@ abstract class BaseQuery
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
protected function tableStr(string $table): array|string
|
||||
protected function tableStr(string $table): array | string
|
||||
{
|
||||
if (!str_contains($table, ',')) {
|
||||
// 单表
|
||||
if (str_contains($table, ' ')) {
|
||||
[$item, $alias] = explode(' ', $table);
|
||||
$table = [];
|
||||
$table = [];
|
||||
$this->alias([$item => $alias]);
|
||||
$table[$item] = $alias;
|
||||
}
|
||||
} else {
|
||||
// 多表
|
||||
$tables = explode(',', $table);
|
||||
$table = [];
|
||||
$table = [];
|
||||
|
||||
foreach ($tables as $item) {
|
||||
$item = trim($item);
|
||||
@ -654,7 +754,7 @@ abstract class BaseQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function order(string|array|Raw $field, string $order = '')
|
||||
public function order(string | array | Raw $field, string $order = '')
|
||||
{
|
||||
if (empty($field)) {
|
||||
return $this;
|
||||
@ -700,14 +800,14 @@ abstract class BaseQuery
|
||||
/**
|
||||
* 分页查询.
|
||||
*
|
||||
* @param int|array $listRows 每页数量 数组表示配置参数
|
||||
* @param int|bool $simple 是否简洁模式或者总记录数
|
||||
*
|
||||
* @throws Exception
|
||||
* @param int|array|null $listRows 每页数量 数组表示配置参数
|
||||
* @param int|bool $simple 是否简洁模式或者总记录数
|
||||
*
|
||||
* @return Paginator
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function paginate(int|array $listRows = null, int|bool $simple = false): Paginator
|
||||
public function paginate(int | array | null $listRows = null, int | bool $simple = false): Paginator
|
||||
{
|
||||
if (is_int($simple)) {
|
||||
$total = $simple;
|
||||
@ -715,18 +815,18 @@ abstract class BaseQuery
|
||||
}
|
||||
|
||||
$defaultConfig = [
|
||||
'query' => [], //url额外参数
|
||||
'fragment' => '', //url锚点
|
||||
'var_page' => 'page', //分页变量
|
||||
'query' => [], //url额外参数
|
||||
'fragment' => '', //url锚点
|
||||
'var_page' => 'page', //分页变量
|
||||
'list_rows' => 15, //每页数量
|
||||
];
|
||||
|
||||
if (is_array($listRows)) {
|
||||
$config = array_merge($defaultConfig, $listRows);
|
||||
$listRows = intval($config['list_rows']);
|
||||
$config = array_merge($defaultConfig, $listRows);
|
||||
$listRows = intval($config['list_rows']);
|
||||
} else {
|
||||
$config = $defaultConfig;
|
||||
$listRows = intval($listRows ?: $config['list_rows']);
|
||||
$config = $defaultConfig;
|
||||
$listRows = intval($listRows ?: $config['list_rows']);
|
||||
}
|
||||
|
||||
$page = isset($config['page']) ? (int) $config['page'] : Paginator::getCurrentPage($config['var_page']);
|
||||
@ -738,8 +838,8 @@ abstract class BaseQuery
|
||||
|
||||
unset($this->options['order'], $this->options['cache'], $this->options['limit'], $this->options['page'], $this->options['field']);
|
||||
|
||||
$bind = $this->bind;
|
||||
$total = $this->count();
|
||||
$bind = $this->bind;
|
||||
$total = $this->count();
|
||||
if ($total > 0) {
|
||||
$results = $this->options($options)->bind($bind)->page($page, $listRows)->select();
|
||||
} else {
|
||||
@ -750,10 +850,10 @@ abstract class BaseQuery
|
||||
}
|
||||
}
|
||||
} elseif ($simple) {
|
||||
$results = $this->limit(($page - 1) * $listRows, $listRows + 1)->select();
|
||||
$total = null;
|
||||
$results = $this->limit(($page - 1) * $listRows, $listRows + 1)->select();
|
||||
$total = null;
|
||||
} else {
|
||||
$results = $this->page($page, $listRows)->select();
|
||||
$results = $this->page($page, $listRows)->select();
|
||||
}
|
||||
|
||||
$this->removeOption('limit');
|
||||
@ -765,32 +865,32 @@ abstract class BaseQuery
|
||||
/**
|
||||
* 根据数字类型字段进行分页查询(大数据).
|
||||
*
|
||||
* @param int|array $listRows 每页数量或者分页配置
|
||||
* @param string $key 分页索引键
|
||||
* @param string $sort 索引键排序 asc|desc
|
||||
*
|
||||
* @throws Exception
|
||||
* @param int|array|null $listRows 每页数量或者分页配置
|
||||
* @param string|null $key 分页索引键
|
||||
* @param string|null $sort 索引键排序 asc|desc
|
||||
*
|
||||
* @return Paginator
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function paginateX(int|array $listRows = null, string $key = null, string $sort = null): Paginator
|
||||
public function paginateX(int | array | null $listRows = null, ?string $key = null, ?string $sort = null): Paginator
|
||||
{
|
||||
$defaultConfig = [
|
||||
'query' => [], //url额外参数
|
||||
'fragment' => '', //url锚点
|
||||
'var_page' => 'page', //分页变量
|
||||
'query' => [], //url额外参数
|
||||
'fragment' => '', //url锚点
|
||||
'var_page' => 'page', //分页变量
|
||||
'list_rows' => 15, //每页数量
|
||||
];
|
||||
|
||||
$config = is_array($listRows) ? array_merge($defaultConfig, $listRows) : $defaultConfig;
|
||||
$listRows = is_int($listRows) ? $listRows : (int) $config['list_rows'];
|
||||
$page = isset($config['page']) ? (int) $config['page'] : Paginator::getCurrentPage($config['var_page']);
|
||||
$page = max($page, 1);
|
||||
$config = is_array($listRows) ? array_merge($defaultConfig, $listRows) : $defaultConfig;
|
||||
$listRows = is_int($listRows) ? $listRows : (int) $config['list_rows'];
|
||||
$page = isset($config['page']) ? (int) $config['page'] : Paginator::getCurrentPage($config['var_page']);
|
||||
$page = max($page, 1);
|
||||
|
||||
$config['path'] = $config['path'] ?? Paginator::getCurrentPath();
|
||||
|
||||
$key = $key ?: $this->getPk();
|
||||
$options = $this->getOptions();
|
||||
$key = $key ?: $this->getPk();
|
||||
$options = $this->getOptions();
|
||||
|
||||
if (is_null($sort)) {
|
||||
$order = $options['order'] ?? '';
|
||||
@ -837,16 +937,16 @@ abstract class BaseQuery
|
||||
/**
|
||||
* 根据最后ID查询更多N个数据.
|
||||
*
|
||||
* @param int $limit LIMIT
|
||||
* @param int|string $lastId LastId
|
||||
* @param string $key 分页索引键 默认为主键
|
||||
* @param string $sort 索引键排序 asc|desc
|
||||
*
|
||||
* @throws Exception
|
||||
* @param int $limit 数量
|
||||
* @param int|string|null $lastId 最后ID
|
||||
* @param string|null $key 分页索引键 默认为主键
|
||||
* @param string|null $sort 索引键排序 asc|desc
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function more(int $limit, int|string $lastId = null, string $key = null, string $sort = null): array
|
||||
public function more(int $limit, int | string | null $lastId = null, ?string $key = null, ?string $sort = null): array
|
||||
{
|
||||
$key = $key ?: $this->getPk();
|
||||
|
||||
@ -901,12 +1001,12 @@ abstract class BaseQuery
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($key instanceof \DateTimeInterface || $key instanceof \DateInterval || (is_int($key) && is_null($expire))) {
|
||||
if ($key instanceof \DateTimeInterface || $key instanceof \DateInterval || (is_int($key) && is_null($expire))) {
|
||||
$expire = $key;
|
||||
$key = true;
|
||||
}
|
||||
|
||||
$this->options['cache'] = [$key, $expire, $tag ?: $this->getTable()];
|
||||
$this->options['cache'] = [$key, $expire, $tag ?: var_export($this->getTable(), true)];
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -921,7 +1021,7 @@ abstract class BaseQuery
|
||||
*/
|
||||
public function cacheAlways($key = true, $expire = null, $tag = null)
|
||||
{
|
||||
$this->options['cache_always'] = true;
|
||||
$this->options['cache_always'] = true;
|
||||
return $this->cache($key, $expire, $tag);
|
||||
}
|
||||
|
||||
@ -936,7 +1036,7 @@ abstract class BaseQuery
|
||||
*/
|
||||
public function cacheForce($key = true, $expire = null, $tag = null)
|
||||
{
|
||||
$this->options['force_cache'] = true;
|
||||
$this->options['force_cache'] = true;
|
||||
|
||||
return $this->cache($key, $expire, $tag);
|
||||
}
|
||||
@ -948,7 +1048,7 @@ abstract class BaseQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function lock(bool|string $lock = false)
|
||||
public function lock(bool | string $lock = false)
|
||||
{
|
||||
$this->options['lock'] = $lock;
|
||||
|
||||
@ -966,7 +1066,7 @@ abstract class BaseQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function alias(array|string $alias)
|
||||
public function alias(array | string $alias)
|
||||
{
|
||||
if (is_array($alias)) {
|
||||
$this->options['alias'] = $alias;
|
||||
@ -1010,11 +1110,11 @@ abstract class BaseQuery
|
||||
/**
|
||||
* 设置自增序列名.
|
||||
*
|
||||
* @param string $sequence 自增序列名
|
||||
* @param string|null $sequence 自增序列名
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function sequence(string $sequence = null)
|
||||
public function sequence(?string $sequence = null)
|
||||
{
|
||||
$this->options['sequence'] = $sequence;
|
||||
|
||||
@ -1031,8 +1131,8 @@ abstract class BaseQuery
|
||||
*/
|
||||
public function json(array $json = [], bool $assoc = false)
|
||||
{
|
||||
$this->options['json'] = $json;
|
||||
$this->options['json_assoc'] = $assoc;
|
||||
$this->options['json'] = $json;
|
||||
$this->options['json_assoc'] = $assoc;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -1058,7 +1158,7 @@ abstract class BaseQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function pk(string|array|bool $pk)
|
||||
public function pk(string | array | bool $pk)
|
||||
{
|
||||
$this->pk = $pk;
|
||||
|
||||
@ -1252,11 +1352,20 @@ abstract class BaseQuery
|
||||
$this->where($this->model->getWhere());
|
||||
}
|
||||
|
||||
if (empty($this->options['where'])) {
|
||||
if (empty($this->options['where']) && empty($this->options['scope'])) {
|
||||
// 如果没有任何更新条件则不执行
|
||||
throw new Exception('miss update condition');
|
||||
}
|
||||
|
||||
// 检查只读字段
|
||||
if (!empty($this->options['readonly_fields'])) {
|
||||
foreach ($this->options['readonly_fields'] as $field) {
|
||||
if (array_key_exists($field, $this->options['data'])) {
|
||||
unset($this->options['data'][$field]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->connection->update($this);
|
||||
}
|
||||
|
||||
@ -1280,7 +1389,7 @@ abstract class BaseQuery
|
||||
$this->where($this->model->getWhere());
|
||||
}
|
||||
|
||||
if (true !== $data && empty($this->options['where'])) {
|
||||
if (true !== $data && empty($this->options['where']) && empty($this->options['scope'])) {
|
||||
// 如果条件为空 不进行删除操作 除非设置 1=1
|
||||
throw new Exception('delete without condition');
|
||||
}
|
||||
@ -1306,11 +1415,7 @@ abstract class BaseQuery
|
||||
*
|
||||
* @param array $data 主键数据
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DataNotFoundException
|
||||
*
|
||||
* @return Collection|array|static[]
|
||||
* @return \think\model\Collection|\think\Collection
|
||||
*/
|
||||
public function select(array $data = []): Collection
|
||||
{
|
||||
@ -1340,22 +1445,25 @@ abstract class BaseQuery
|
||||
/**
|
||||
* 查找单条记录.
|
||||
*
|
||||
* @param mixed $data 主键数据
|
||||
* @param mixed $data 主键数据
|
||||
* @param ?Closure $closure 闭包数据
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DataNotFoundException
|
||||
*
|
||||
* @return mixed
|
||||
* @return static|\think\Model|array|null
|
||||
*/
|
||||
public function find($data = null)
|
||||
public function find($data = null, ?Closure $closure = null)
|
||||
{
|
||||
if (!is_null($data)) {
|
||||
if ($data instanceof Closure) {
|
||||
$closure = $data;
|
||||
} elseif (!is_null($data)) {
|
||||
// AR模式分析主键条件
|
||||
$this->parsePkWhere($data);
|
||||
}
|
||||
|
||||
if (empty($this->options['where']) && empty($this->options['order'])) {
|
||||
if (empty($this->options['where']) && empty($this->options['scope']) && empty($this->options['order']) && empty($this->options['sort'])) {
|
||||
$result = [];
|
||||
} else {
|
||||
$result = $this->connection->find($this);
|
||||
@ -1363,7 +1471,7 @@ abstract class BaseQuery
|
||||
|
||||
// 数据处理
|
||||
if (empty($result)) {
|
||||
return $this->resultToEmpty();
|
||||
return $this->resultToEmpty($closure);
|
||||
}
|
||||
|
||||
if (!empty($this->model)) {
|
||||
@ -1383,6 +1491,9 @@ abstract class BaseQuery
|
||||
*/
|
||||
public function parseOptions(): array
|
||||
{
|
||||
// 执行全局查询范围
|
||||
$this->scopeQuery();
|
||||
|
||||
$options = $this->getOptions();
|
||||
|
||||
// 获取数据表
|
||||
@ -1423,9 +1534,9 @@ abstract class BaseQuery
|
||||
// 根据页数计算limit
|
||||
[$page, $listRows] = $options['page'];
|
||||
|
||||
$page = $page > 0 ? $page : 1;
|
||||
$listRows = $listRows ?: (is_numeric($options['limit']) ? $options['limit'] : 20);
|
||||
$offset = $listRows * ($page - 1);
|
||||
$page = $page > 0 ? $page : 1;
|
||||
$listRows = $listRows ?: (is_numeric($options['limit']) ? $options['limit'] : 20);
|
||||
$offset = $listRows * ($page - 1);
|
||||
|
||||
$options['limit'] = $offset . ',' . $listRows;
|
||||
}
|
||||
@ -1446,7 +1557,7 @@ abstract class BaseQuery
|
||||
*/
|
||||
public function parseUpdateData(array &$data): bool
|
||||
{
|
||||
$pk = $this->getPk();
|
||||
$pk = $this->getPk();
|
||||
$isUpdate = false;
|
||||
// 如果存在主键数据 则自动作为更新条件
|
||||
if (is_string($pk) && isset($data[$pk])) {
|
||||
|
||||
95
vendor/topthink/think-orm/src/db/Builder.php
vendored
Executable file → Normal file
95
vendor/topthink/think-orm/src/db/Builder.php
vendored
Executable file → Normal file
@ -9,14 +9,16 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db;
|
||||
|
||||
use BackedEnum;
|
||||
use Closure;
|
||||
use Stringable;
|
||||
use think\db\BaseQuery as Query;
|
||||
use think\db\exception\DbException as Exception;
|
||||
use UnitEnum;
|
||||
|
||||
/**
|
||||
* Db Builder.
|
||||
@ -59,30 +61,34 @@ class Builder extends BaseBuilder
|
||||
|
||||
foreach ($data as $key => $val) {
|
||||
$item = $this->parseKey($query, $key, true);
|
||||
|
||||
if ($val instanceof Raw) {
|
||||
if ($val instanceof BackedEnum) {
|
||||
$val = $val->value;
|
||||
} elseif ($val instanceof UnitEnum) {
|
||||
$val = $val->name;
|
||||
} elseif ($val instanceof Raw) {
|
||||
$result[$item] = $this->parseRaw($query, $val);
|
||||
continue;
|
||||
} elseif (is_null($val) && in_array($key, $fields, true)) {
|
||||
$result[$item] = 'NULL';
|
||||
continue;
|
||||
} elseif (!is_scalar($val) && (in_array($key, (array) $query->getOptions('json')) || 'json' == $query->getFieldType($key))) {
|
||||
$val = json_encode($val);
|
||||
}
|
||||
|
||||
if (str_contains($key, '->')) {
|
||||
[$key, $name] = explode('->', $key, 2);
|
||||
$item = $this->parseKey($query, $key);
|
||||
$item = $this->parseKey($query, $key);
|
||||
|
||||
$result[$item . '->' . $name] = 'json_set(' . $item . ', \'$.' . $name . '\', ' . $this->parseDataBind($query, $key . '->' . $name, $val, $bind) . ')';
|
||||
} elseif (!str_contains($key, '.') && !in_array($key, $fields, true)) {
|
||||
if ($options['strict']) {
|
||||
throw new Exception('fields not exists:[' . $key . ']');
|
||||
}
|
||||
} elseif (is_null($val)) {
|
||||
$result[$item] = 'NULL';
|
||||
} elseif (is_array($val) && !empty($val) && is_string($val[0])) {
|
||||
if (in_array(strtoupper($val[0]), ['INC', 'DEC'])) {
|
||||
$result[$item] = match (strtoupper($val[0])) {
|
||||
'INC' => $item . ' + ' . floatval($val[1]),
|
||||
'DEC' => $item . ' - ' . floatval($val[1]),
|
||||
$result[$item] = match (strtoupper($val[0])) {
|
||||
'INC' => $item . ' + ' . floatval($val[1]),
|
||||
'DEC' => $item . ' - ' . floatval($val[1]),
|
||||
};
|
||||
}
|
||||
} elseif (is_scalar($val)) {
|
||||
@ -127,7 +133,7 @@ class Builder extends BaseBuilder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function parseKey(Query $query, string|int|Raw $key, bool $strict = false): string
|
||||
public function parseKey(Query $query, string | int | Raw $key, bool $strict = false): string
|
||||
{
|
||||
return $key;
|
||||
}
|
||||
@ -155,26 +161,23 @@ class Builder extends BaseBuilder
|
||||
*/
|
||||
protected function parseField(Query $query, array $fields): string
|
||||
{
|
||||
if (!empty($fields)) {
|
||||
// 支持 'field1'=>'field2' 这样的字段别名定义
|
||||
$array = [];
|
||||
|
||||
foreach ($fields as $key => $field) {
|
||||
if ($field instanceof Raw) {
|
||||
$array[] = $this->parseRaw($query, $field);
|
||||
} elseif (!is_numeric($key)) {
|
||||
$array[] = $this->parseKey($query, $key) . ' AS ' . $this->parseKey($query, $field, true);
|
||||
} else {
|
||||
$array[] = $this->parseKey($query, $field);
|
||||
}
|
||||
}
|
||||
|
||||
$fieldsStr = implode(',', $array);
|
||||
} else {
|
||||
$fieldsStr = '*';
|
||||
if (empty($fields)) {
|
||||
return '*';
|
||||
}
|
||||
|
||||
return $fieldsStr;
|
||||
// 支持 'field1' => 'field2' 这样的字段别名定义
|
||||
$array = array_map(function ($field, $key) use ($query) {
|
||||
if ($field instanceof Raw) {
|
||||
return $this->parseRaw($query, $field);
|
||||
} elseif (!is_numeric($key)) {
|
||||
// 字段别名定义
|
||||
return $this->parseKey($query, $key) . ' AS ' . $this->parseKey($query, $field, true);
|
||||
} else {
|
||||
return $this->parseKey($query, $field);
|
||||
}
|
||||
}, $fields, array_keys($fields));
|
||||
|
||||
return implode(',', $array);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -185,9 +188,9 @@ class Builder extends BaseBuilder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function parseTable(Query $query, array|string $tables): string
|
||||
protected function parseTable(Query $query, array | string $tables): string
|
||||
{
|
||||
$item = [];
|
||||
$item = [];
|
||||
$options = $query->getOptions();
|
||||
|
||||
foreach ((array) $tables as $key => $table) {
|
||||
@ -215,14 +218,14 @@ class Builder extends BaseBuilder
|
||||
*/
|
||||
protected function parseWhere(Query $query, array $where): string
|
||||
{
|
||||
$options = $query->getOptions();
|
||||
$options = $query->getOptions();
|
||||
$whereStr = $this->buildWhere($query, $where);
|
||||
|
||||
if (!empty($options['soft_delete'])) {
|
||||
// 附加软删除条件
|
||||
[$field, $condition] = $options['soft_delete'];
|
||||
|
||||
$binds = $query->getFieldsBindType();
|
||||
$binds = $query->getFieldsBindType();
|
||||
$whereStr = $whereStr ? '( ' . $whereStr . ' ) AND ' : '';
|
||||
$whereStr = $whereStr . $this->parseWhereItem($query, $field, $condition, $binds);
|
||||
}
|
||||
@ -267,12 +270,16 @@ class Builder extends BaseBuilder
|
||||
} elseif ($value instanceof Stringable) {
|
||||
// 对象数据写入
|
||||
$value = $value->__toString();
|
||||
} elseif ($value instanceof BackedEnum) {
|
||||
$value = $value->value;
|
||||
} elseif ($value instanceof UnitEnum) {
|
||||
$value = $value->name;
|
||||
}
|
||||
|
||||
if (is_scalar($value) && !in_array($exp, ['EXP', 'NOT NULL', 'NULL', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN']) && !str_contains($exp, 'TIME')) {
|
||||
if (is_string($value) && str_starts_with($value, ':') && $query->isBind(substr($value, 1))) {
|
||||
} else {
|
||||
$name = $query->bindValue($value, $bindType);
|
||||
$name = $query->bindValue($value, $bindType);
|
||||
$value = ':' . $name;
|
||||
}
|
||||
}
|
||||
@ -306,7 +313,7 @@ class Builder extends BaseBuilder
|
||||
if (is_array($value)) {
|
||||
$array = [];
|
||||
foreach ($value as $item) {
|
||||
$name = $query->bindValue($item, Connection::PARAM_STR);
|
||||
$name = $query->bindValue($item, Connection::PARAM_STR);
|
||||
$array[] = $key . ' ' . $exp . ' :' . $name;
|
||||
}
|
||||
|
||||
@ -366,7 +373,7 @@ class Builder extends BaseBuilder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function parseBetween(Query $query, string $key, string $exp, array|string $value, $field, int $bindType): string
|
||||
protected function parseBetween(Query $query, string $key, string $exp, array | string $value, $field, int $bindType): string
|
||||
{
|
||||
// BETWEEN 查询
|
||||
$data = is_array($value) ? $value : explode(',', $value);
|
||||
@ -405,8 +412,8 @@ class Builder extends BaseBuilder
|
||||
if ($query->isAutoBind()) {
|
||||
$array = [];
|
||||
foreach ($value as $v) {
|
||||
$name = $query->bindValue($v, $bindType);
|
||||
$array[] = ':' . $name;
|
||||
$name = $query->bindValue($v, $bindType);
|
||||
$array[] = ':' . $name;
|
||||
}
|
||||
$value = implode(',', $array);
|
||||
} elseif (Connection::PARAM_STR == $bindType) {
|
||||
@ -541,8 +548,8 @@ class Builder extends BaseBuilder
|
||||
}
|
||||
|
||||
if (preg_match('/^[\w\.]+$/', $key)) {
|
||||
$sort = strtoupper($sort);
|
||||
$sort = in_array($sort, ['ASC', 'DESC'], true) ? ' ' . $sort : '';
|
||||
$sort = strtoupper($sort);
|
||||
$sort = in_array($sort, ['ASC', 'DESC'], true) ? ' ' . $sort : '';
|
||||
$array[] = $this->parseKey($query, $key, true) . $sort;
|
||||
} else {
|
||||
throw new Exception('order express error:' . $key);
|
||||
@ -563,8 +570,8 @@ class Builder extends BaseBuilder
|
||||
*/
|
||||
protected function parseRaw(Query $query, Raw $raw): string
|
||||
{
|
||||
$sql = $raw->getValue();
|
||||
$bind = $raw->getBind();
|
||||
$sql = $raw->getValue();
|
||||
$bind = $raw->getBind();
|
||||
|
||||
if ($bind) {
|
||||
$query->bindParams($sql, $bind);
|
||||
@ -622,7 +629,7 @@ class Builder extends BaseBuilder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function parseGroup(Query $query, string|array $group): string
|
||||
protected function parseGroup(Query $query, string | array $group): string
|
||||
{
|
||||
if (empty($group)) {
|
||||
return '';
|
||||
@ -691,7 +698,7 @@ class Builder extends BaseBuilder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function parseForce(Query $query, string|array $index): string
|
||||
protected function parseForce(Query $query, string | array $index): string
|
||||
{
|
||||
if (empty($index)) {
|
||||
return '';
|
||||
@ -712,7 +719,7 @@ class Builder extends BaseBuilder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function parseLock(Query $query, bool|string $lock = false): string
|
||||
protected function parseLock(Query $query, bool | string $lock = false): string
|
||||
{
|
||||
if (is_bool($lock)) {
|
||||
return $lock ? ' FOR UPDATE ' : '';
|
||||
|
||||
2
vendor/topthink/think-orm/src/db/CacheItem.php
vendored
Executable file → Normal file
2
vendor/topthink/think-orm/src/db/CacheItem.php
vendored
Executable file → Normal file
@ -58,7 +58,7 @@ class CacheItem
|
||||
*/
|
||||
protected $isHit = false;
|
||||
|
||||
public function __construct(string $key = null)
|
||||
public function __construct(?string $key = null)
|
||||
{
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
15
vendor/topthink/think-orm/src/db/Connection.php
vendored
Executable file → Normal file
15
vendor/topthink/think-orm/src/db/Connection.php
vendored
Executable file → Normal file
@ -9,7 +9,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db;
|
||||
|
||||
@ -282,7 +282,7 @@ abstract class Connection implements ConnectionInterface
|
||||
}
|
||||
|
||||
$runtime = number_format((microtime(true) - $this->queryStartTime), 6);
|
||||
$sql = $sql ?: $this->getLastsql();
|
||||
$sql = $sql ?: $this->getLastsql();
|
||||
|
||||
if (empty($this->config['deploy'])) {
|
||||
$master = null;
|
||||
@ -320,7 +320,7 @@ abstract class Connection implements ConnectionInterface
|
||||
protected function getCacheKey(BaseQuery $query, string $method = ''): string
|
||||
{
|
||||
if (!empty($query->getOptions('key')) && empty($method)) {
|
||||
$key = 'think_' . $this->getConfig('database') . '.' . $query->getTable() . '|' . $query->getOptions('key');
|
||||
$key = 'think_' . $this->getConfig('database') . '.' . var_export($query->getTable(), true) . '|' . $query->getOptions('key');
|
||||
} else {
|
||||
$key = $query->getQueryGuid();
|
||||
}
|
||||
@ -378,7 +378,7 @@ abstract class Connection implements ConnectionInterface
|
||||
{
|
||||
foreach ($bind as $key => $val) {
|
||||
$value = strval(is_array($val) ? $val[0] : $val);
|
||||
$type = is_array($val) ? $val[1] : self::PARAM_STR;
|
||||
$type = is_array($val) ? $val[1] : self::PARAM_STR;
|
||||
|
||||
if (self::PARAM_FLOAT == $type || self::PARAM_STR == $type) {
|
||||
$value = '\'' . addslashes($value) . '\'';
|
||||
@ -388,8 +388,11 @@ abstract class Connection implements ConnectionInterface
|
||||
|
||||
// 判断占位符
|
||||
$sql = is_numeric($key) ?
|
||||
substr_replace($sql, $value, strpos($sql, '?'), 1) :
|
||||
substr_replace($sql, $value, strpos($sql, ':' . $key), strlen(':' . $key));
|
||||
substr_replace($sql, $value, strpos($sql, '?'), 1) :
|
||||
str_replace(
|
||||
[':' . $key . ' ', ':' . $key . ',', ':' . $key . ')'],
|
||||
[$value . ' ', $value . ',', $value . ')'],
|
||||
$sql);
|
||||
}
|
||||
|
||||
return rtrim($sql);
|
||||
|
||||
2
vendor/topthink/think-orm/src/db/ConnectionInterface.php
vendored
Executable file → Normal file
2
vendor/topthink/think-orm/src/db/ConnectionInterface.php
vendored
Executable file → Normal file
@ -222,5 +222,5 @@ interface ConnectionInterface
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLastInsID(BaseQuery $query, string $sequence = null);
|
||||
public function getLastInsID(BaseQuery $query, ?string $sequence = null);
|
||||
}
|
||||
|
||||
52
vendor/topthink/think-orm/src/db/Fetch.php
vendored
Executable file → Normal file
52
vendor/topthink/think-orm/src/db/Fetch.php
vendored
Executable file → Normal file
@ -9,7 +9,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db;
|
||||
|
||||
@ -43,8 +43,8 @@ class Fetch
|
||||
*/
|
||||
public function __construct(protected Query $query)
|
||||
{
|
||||
$this->connection = $query->getConnection();
|
||||
$this->builder = $this->connection->getBuilder();
|
||||
$this->connection = $query->getConnection();
|
||||
$this->builder = $this->connection->getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -198,7 +198,7 @@ class Fetch
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function insertAll(array $dataSet = [], int $limit = null): string
|
||||
public function insertAll(array $dataSet = [], ?int $limit = null): string
|
||||
{
|
||||
$options = $this->query->parseOptions();
|
||||
|
||||
@ -211,10 +211,10 @@ class Fetch
|
||||
}
|
||||
|
||||
if ($limit) {
|
||||
$array = array_chunk($dataSet, $limit, true);
|
||||
$array = array_chunk($dataSet, $limit, true);
|
||||
$fetchSql = [];
|
||||
foreach ($array as $item) {
|
||||
$sql = $this->builder->insertAll($this->query, $item);
|
||||
$sql = $this->builder->insertAll($this->query, $item);
|
||||
$bind = $this->query->getBind();
|
||||
|
||||
$fetchSql[] = $this->connection->getRealSql($sql, $bind);
|
||||
@ -245,6 +245,34 @@ class Fetch
|
||||
return $this->fetch($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字段值增长
|
||||
*
|
||||
* @param string $field 字段名
|
||||
* @param float $step 步进值
|
||||
* @param int $lazyTime 延迟时间(秒)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function setInc(string $field, float $step = 1, int $lazyTime = 0)
|
||||
{
|
||||
return $this->inc($field, $step)->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* 字段值减少
|
||||
*
|
||||
* @param string $field 字段名
|
||||
* @param float $step 步进值
|
||||
* @param int $lazyTime 延迟时间(秒)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function setDec(string $field, float $step = 1, int $lazyTime = 0)
|
||||
{
|
||||
return $this->dec($field, $step)->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新记录.
|
||||
*
|
||||
@ -316,7 +344,7 @@ class Fetch
|
||||
$this->query->setOption('soft_delete', null);
|
||||
$this->query->setOption('data', [$field => $condition]);
|
||||
// 生成删除SQL语句
|
||||
$sql = $this->builder->delete($this->query);
|
||||
$sql = $this->builder->update($this->query);
|
||||
|
||||
return $this->fetch($sql);
|
||||
}
|
||||
@ -437,12 +465,12 @@ class Fetch
|
||||
if (!empty($options['group'])) {
|
||||
// 支持GROUP
|
||||
$subSql = $this->query->field('count(' . $field . ') AS think_count')->buildSql();
|
||||
$query = $this->query->newQuery()->table([$subSql => '_group_count_']);
|
||||
$query = $this->query->newQuery()->table([$subSql => '_group_count_']);
|
||||
|
||||
return $query->fetchsql()->aggregate('COUNT', '*');
|
||||
} else {
|
||||
return $this->aggregate('COUNT', $field);
|
||||
}
|
||||
|
||||
return $this->aggregate('COUNT', $field);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -500,7 +528,9 @@ class Fetch
|
||||
$field = Str::snake(substr($method, 5));
|
||||
|
||||
return $this->where($field, '=', $args[0])->find();
|
||||
} elseif (strtolower(substr($method, 0, 10)) == 'getfieldby') {
|
||||
}
|
||||
|
||||
if (strtolower(substr($method, 0, 10)) == 'getfieldby') {
|
||||
// 根据某个字段获取记录的某个值
|
||||
$name = Str::snake(substr($method, 10));
|
||||
|
||||
|
||||
6
vendor/topthink/think-orm/src/db/Mongo.php
vendored
Executable file → Normal file
6
vendor/topthink/think-orm/src/db/Mongo.php
vendored
Executable file → Normal file
@ -46,7 +46,7 @@ class Mongo extends BaseQuery
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function command(Command $command, string $dbName = '', ReadPreference $readPreference = null, $typeMap = null)
|
||||
public function command(Command $command, string $dbName = '', ?ReadPreference $readPreference = null, $typeMap = null)
|
||||
{
|
||||
return $this->connection->command($command, $dbName, $readPreference, $typeMap);
|
||||
}
|
||||
@ -106,7 +106,7 @@ class Mongo extends BaseQuery
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count(string $field = null): int
|
||||
public function count(?string $field = null): int
|
||||
{
|
||||
$result = $this->cmd('count');
|
||||
|
||||
@ -462,7 +462,7 @@ class Mongo extends BaseQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function limit(int $offset, int $length = null)
|
||||
public function limit(int $offset, ?int $length = null)
|
||||
{
|
||||
if (is_null($length)) {
|
||||
$length = $offset;
|
||||
|
||||
287
vendor/topthink/think-orm/src/db/PDOConnection.php
vendored
Executable file → Normal file
287
vendor/topthink/think-orm/src/db/PDOConnection.php
vendored
Executable file → Normal file
@ -9,7 +9,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db;
|
||||
|
||||
@ -163,12 +163,16 @@ abstract class PDOConnection extends Connection
|
||||
protected $bindType = [
|
||||
'string' => self::PARAM_STR,
|
||||
'str' => self::PARAM_STR,
|
||||
'bigint' => self::PARAM_STR,
|
||||
'set' => self::PARAM_STR,
|
||||
'enum' => self::PARAM_STR,
|
||||
'integer' => self::PARAM_INT,
|
||||
'int' => self::PARAM_INT,
|
||||
'boolean' => self::PARAM_BOOL,
|
||||
'bool' => self::PARAM_BOOL,
|
||||
'float' => self::PARAM_FLOAT,
|
||||
'datetime' => self::PARAM_STR,
|
||||
'date' => self::PARAM_STR,
|
||||
'timestamp' => self::PARAM_STR,
|
||||
];
|
||||
|
||||
@ -276,10 +280,10 @@ abstract class PDOConnection extends Connection
|
||||
{
|
||||
// 字段大小写转换
|
||||
return match ($this->attrCase) {
|
||||
PDO::CASE_LOWER => array_change_key_case($info),
|
||||
PDO::CASE_UPPER => array_change_key_case($info, CASE_UPPER),
|
||||
PDO::CASE_NATURAL => $info,
|
||||
default => $info,
|
||||
PDO::CASE_LOWER => array_change_key_case($info),
|
||||
PDO::CASE_UPPER => array_change_key_case($info, CASE_UPPER),
|
||||
PDO::CASE_NATURAL => $info,
|
||||
default => $info,
|
||||
};
|
||||
}
|
||||
|
||||
@ -292,25 +296,24 @@ abstract class PDOConnection extends Connection
|
||||
*/
|
||||
protected function getFieldType(string $type): string
|
||||
{
|
||||
if (0 === stripos($type, 'set') || 0 === stripos($type, 'enum')) {
|
||||
$result = 'string';
|
||||
} elseif (preg_match('/(double|float|decimal|real|numeric)/is', $type)) {
|
||||
$result = 'float';
|
||||
} elseif (preg_match('/(int|serial|bit)/is', $type)) {
|
||||
$result = 'int';
|
||||
} elseif (preg_match('/bool/is', $type)) {
|
||||
$result = 'bool';
|
||||
} elseif (0 === stripos($type, 'timestamp')) {
|
||||
$result = 'timestamp';
|
||||
} elseif (0 === stripos($type, 'datetime')) {
|
||||
$result = 'datetime';
|
||||
} elseif (0 === stripos($type, 'date')) {
|
||||
$result = 'date';
|
||||
} else {
|
||||
$result = 'string';
|
||||
}
|
||||
// 将字段类型转换为小写以进行比较
|
||||
$type = strtolower($type);
|
||||
|
||||
return $result;
|
||||
return match (true) {
|
||||
str_starts_with($type, 'set') => 'set',
|
||||
str_starts_with($type, 'enum') => 'enum',
|
||||
str_starts_with($type, 'bigint') => 'bigint',
|
||||
str_contains($type, 'float') || str_contains($type, 'double') ||
|
||||
str_contains($type, 'decimal') || str_contains($type, 'real') ||
|
||||
str_contains($type, 'numeric') => 'float',
|
||||
str_contains($type, 'int') || str_contains($type, 'serial') ||
|
||||
str_contains($type, 'bit') => 'int',
|
||||
str_contains($type, 'bool') => 'bool',
|
||||
str_starts_with($type, 'timestamp') => 'timestamp',
|
||||
str_starts_with($type, 'datetime') => 'datetime',
|
||||
str_starts_with($type, 'date') => 'date',
|
||||
default => 'string',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -322,21 +325,7 @@ abstract class PDOConnection extends Connection
|
||||
*/
|
||||
public function getFieldBindType(string $type): int
|
||||
{
|
||||
if (in_array($type, ['integer', 'string', 'float', 'boolean', 'bool', 'int', 'str'])) {
|
||||
$bind = $this->bindType[$type];
|
||||
} elseif (str_starts_with($type, 'set') || str_starts_with($type, 'enum')) {
|
||||
$bind = self::PARAM_STR;
|
||||
} elseif (preg_match('/(double|float|decimal|real|numeric)/is', $type)) {
|
||||
$bind = self::PARAM_FLOAT;
|
||||
} elseif (preg_match('/(int|serial|bit)/is', $type)) {
|
||||
$bind = self::PARAM_INT;
|
||||
} elseif (preg_match('/bool/is', $type)) {
|
||||
$bind = self::PARAM_BOOL;
|
||||
} else {
|
||||
$bind = self::PARAM_STR;
|
||||
}
|
||||
|
||||
return $bind;
|
||||
return $this->bindType[$type] ?? self::PARAM_STR;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -348,7 +337,8 @@ abstract class PDOConnection extends Connection
|
||||
*/
|
||||
protected function getSchemaCacheKey(string $schema): string
|
||||
{
|
||||
return $this->getConfig('hostname') . '_' . $this->getConfig('hostport') . '|' . $schema;
|
||||
$hostname = $this->getConfig('hostname');
|
||||
return (is_array($hostname) ? $hostname[0] : $hostname) . '_' . $this->getConfig('hostport') . '|' . $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -357,49 +347,59 @@ abstract class PDOConnection extends Connection
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSchemaInfo(string $tableName, $force = false)
|
||||
public function getSchemaInfo(string $tableName, bool $force = false): array
|
||||
{
|
||||
if (!str_contains($tableName, '.')) {
|
||||
$schema = $this->getConfig('database') . '.' . $tableName;
|
||||
} else {
|
||||
$schema = $tableName;
|
||||
$schema = str_contains($tableName, '.') ? $tableName : $this->getConfig('database') . '.' . $tableName;
|
||||
|
||||
if (isset($this->info[$schema]) && !$force) {
|
||||
return $this->info[$schema];
|
||||
}
|
||||
|
||||
if (!isset($this->info[$schema]) || $force) {
|
||||
// 读取字段缓存
|
||||
$cacheKey = $this->getSchemaCacheKey($schema);
|
||||
if ($this->config['fields_cache'] && !empty($this->cache) && !$force) {
|
||||
$info = $this->cache->get($cacheKey);
|
||||
}
|
||||
// 读取字段缓存
|
||||
$cacheKey = $this->getSchemaCacheKey($schema);
|
||||
$info = $this->getCachedSchemaInfo($cacheKey, $tableName, $force);
|
||||
|
||||
if (empty($info)) {
|
||||
$info = $this->getTableFieldsInfo($tableName);
|
||||
if (!empty($this->cache) && ($this->config['fields_cache'] || $force)) {
|
||||
$this->cache->set($cacheKey, $info);
|
||||
}
|
||||
}
|
||||
$pk = $info['_pk'] ?? null;
|
||||
$autoinc = $info['_autoinc'] ?? null;
|
||||
unset($info['_pk'], $info['_autoinc']);
|
||||
|
||||
$pk = $info['_pk'] ?? null;
|
||||
$autoinc = $info['_autoinc'] ?? null;
|
||||
unset($info['_pk'], $info['_autoinc']);
|
||||
$bind = array_map(fn($val) => $this->getFieldBindType($val), $info);
|
||||
|
||||
$bind = [];
|
||||
foreach ($info as $name => $val) {
|
||||
$bind[$name] = $this->getFieldBindType($val);
|
||||
}
|
||||
|
||||
$this->info[$schema] = [
|
||||
'fields' => array_keys($info),
|
||||
'type' => $info,
|
||||
'bind' => $bind,
|
||||
'pk' => $pk,
|
||||
'autoinc' => $autoinc,
|
||||
];
|
||||
}
|
||||
$this->info[$schema] = [
|
||||
'fields' => array_keys($info),
|
||||
'type' => $info,
|
||||
'bind' => $bind,
|
||||
'pk' => $pk,
|
||||
'autoinc' => $autoinc,
|
||||
];
|
||||
|
||||
return $this->info[$schema];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $cacheKey 缓存key
|
||||
* @param string $tableName 数据表名称
|
||||
* @param bool $force 强制从数据库获取
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getCachedSchemaInfo(string $cacheKey, string $tableName, bool $force): array
|
||||
{
|
||||
if ($this->config['fields_cache'] && !empty($this->cache) && !$force) {
|
||||
$info = $this->cache->get($cacheKey);
|
||||
if (!empty($info)) {
|
||||
return $info;
|
||||
}
|
||||
}
|
||||
|
||||
$info = $this->getTableFieldsInfo($tableName);
|
||||
if (!empty($this->cache) && ($this->config['fields_cache'] || $force)) {
|
||||
$this->cache->set($cacheKey, $info);
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据表信息.
|
||||
*
|
||||
@ -408,7 +408,7 @@ abstract class PDOConnection extends Connection
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTableInfo($tableName, string $fetch = '')
|
||||
public function getTableInfo(array | string $tableName, string $fetch = '')
|
||||
{
|
||||
if (is_array($tableName)) {
|
||||
$tableName = key($tableName) ?: current($tableName);
|
||||
@ -423,7 +423,7 @@ abstract class PDOConnection extends Connection
|
||||
|
||||
$info = $this->getSchemaInfo($tableName);
|
||||
|
||||
return $fetch ? $info[$fetch] : $info;
|
||||
return $fetch && isset($info[$fetch]) ? $info[$fetch] : $info;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -436,7 +436,7 @@ abstract class PDOConnection extends Connection
|
||||
public function getTableFieldsInfo(string $tableName): array
|
||||
{
|
||||
$fields = $this->getFields($tableName);
|
||||
$info = [];
|
||||
$info = [];
|
||||
|
||||
foreach ($fields as $key => $val) {
|
||||
// 记录字段类型
|
||||
@ -453,7 +453,7 @@ abstract class PDOConnection extends Connection
|
||||
|
||||
if (isset($pk)) {
|
||||
// 设置主键
|
||||
$pk = count($pk) > 1 ? $pk : $pk[0];
|
||||
$pk = count($pk) > 1 ? $pk : $pk[0];
|
||||
$info['_pk'] = $pk;
|
||||
}
|
||||
|
||||
@ -508,7 +508,7 @@ abstract class PDOConnection extends Connection
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
public function getFieldsType($tableName, string $field = null)
|
||||
public function getFieldsType($tableName, ?string $field = null)
|
||||
{
|
||||
$result = $this->getTableInfo($tableName, 'type');
|
||||
|
||||
@ -711,7 +711,7 @@ abstract class PDOConnection extends Connection
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function pdoQuery(BaseQuery $query, $sql, bool $master = null): array
|
||||
protected function pdoQuery(BaseQuery $query, $sql, ?bool $master = null): array
|
||||
{
|
||||
// 分析查询表达式
|
||||
$query->parseOptions();
|
||||
@ -723,16 +723,17 @@ abstract class PDOConnection extends Connection
|
||||
if (!$query->getOptions('force_cache')) {
|
||||
$key = $cacheItem->getKey();
|
||||
|
||||
$data = $this->cache->get($key);
|
||||
|
||||
if (null !== $data) {
|
||||
return $data;
|
||||
if ($this->cache->has($key)) {
|
||||
$data = $this->cache->get($key);
|
||||
if (null !== $data) {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($sql instanceof Closure) {
|
||||
$sql = $sql($query);
|
||||
$sql = $sql($query);
|
||||
$bind = $query->getBind();
|
||||
}
|
||||
|
||||
@ -744,7 +745,7 @@ abstract class PDOConnection extends Connection
|
||||
|
||||
$this->getPDOStatement($sql, $bind, $master, $procedure);
|
||||
|
||||
$resultSet = $this->getResult($procedure);
|
||||
$resultSet = $this->getResult($procedure);
|
||||
$requireCache = $query->getOptions('cache_always') || !empty($resultSet);
|
||||
|
||||
if (isset($cacheItem) && $requireCache) {
|
||||
@ -791,9 +792,8 @@ abstract class PDOConnection extends Connection
|
||||
$this->initConnect($this->readMaster ?: $master);
|
||||
// 记录SQL语句
|
||||
$this->queryStr = $sql;
|
||||
$this->bind = $bind;
|
||||
$this->bind = $bind;
|
||||
|
||||
$this->db->updateQueryTimes();
|
||||
$this->queryStartTime = microtime(true);
|
||||
|
||||
// 预处理
|
||||
@ -817,7 +817,7 @@ abstract class PDOConnection extends Connection
|
||||
$this->reConnectTimes = 0;
|
||||
|
||||
return $this->PDOStatement;
|
||||
} catch (\Throwable | \Exception $e) {
|
||||
} catch (\Throwable | \Exception $e) {
|
||||
if ($this->transTimes > 0) {
|
||||
// 事务活动中时不应该进行重试,应直接中断执行,防止造成污染。
|
||||
if ($this->isBreak($e)) {
|
||||
@ -868,8 +868,8 @@ abstract class PDOConnection extends Connection
|
||||
if ($query->getOptions('cache')) {
|
||||
// 清理缓存数据
|
||||
$cacheItem = $this->parseCache($query, $query->getOptions('cache'));
|
||||
$key = $cacheItem->getKey();
|
||||
$tag = $cacheItem->getTag();
|
||||
$key = $cacheItem->getKey();
|
||||
$tag = $cacheItem->getTag();
|
||||
|
||||
if (isset($key) && $this->cache->has($key)) {
|
||||
$this->cache->delete($key);
|
||||
@ -891,9 +891,9 @@ abstract class PDOConnection extends Connection
|
||||
*/
|
||||
protected function queryPDOStatement(BaseQuery $query, string $sql): PDOStatement
|
||||
{
|
||||
$options = $query->getOptions();
|
||||
$bind = $query->getBind();
|
||||
$master = !empty($options['master']);
|
||||
$options = $query->getOptions();
|
||||
$bind = $query->getBind();
|
||||
$master = !empty($options['master']);
|
||||
$procedure = !empty($options['procedure']) || in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']);
|
||||
|
||||
return $this->getPDOStatement($sql, $bind, $master, $procedure);
|
||||
@ -989,14 +989,14 @@ abstract class PDOConnection extends Connection
|
||||
$result = '' == $sql ? 0 : $this->pdoExecute($query, $sql);
|
||||
|
||||
if ($result) {
|
||||
$sequence = $options['sequence'] ?? null;
|
||||
$sequence = $options['sequence'] ?? null;
|
||||
$lastInsId = $this->getLastInsID($query, $sequence);
|
||||
|
||||
$data = $options['data'];
|
||||
|
||||
if ($lastInsId) {
|
||||
$pk = $query->getAutoInc();
|
||||
if ($pk) {
|
||||
if ($pk && is_string($pk)) {
|
||||
$data[$pk] = $lastInsId;
|
||||
}
|
||||
}
|
||||
@ -1057,7 +1057,7 @@ abstract class PDOConnection extends Connection
|
||||
|
||||
// 提交事务
|
||||
$this->commit();
|
||||
} catch (\Exception | \Throwable $e) {
|
||||
} catch (\Exception | \Throwable $e) {
|
||||
$this->rollback();
|
||||
|
||||
throw $e;
|
||||
@ -1112,7 +1112,7 @@ abstract class PDOConnection extends Connection
|
||||
|
||||
// 提交事务
|
||||
$this->commit();
|
||||
} catch (\Exception | \Throwable $e) {
|
||||
} catch (\Exception | \Throwable $e) {
|
||||
$this->rollback();
|
||||
|
||||
throw $e;
|
||||
@ -1230,7 +1230,10 @@ abstract class PDOConnection extends Connection
|
||||
$key = $cacheItem->getKey();
|
||||
|
||||
if ($this->cache->has($key)) {
|
||||
return $this->cache->get($key);
|
||||
$data = $this->cache->get($key);
|
||||
if (null !== $data) {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1251,28 +1254,30 @@ abstract class PDOConnection extends Connection
|
||||
// 执行查询操作
|
||||
$pdo = $this->getPDOStatement($sql, $query->getBind(), $options['master']);
|
||||
|
||||
$result = $pdo->fetchColumn();
|
||||
$result = $pdo->fetchColumn();
|
||||
$result = false !== $result ? $result : $default;
|
||||
$requireCache = $query->getOptions('cache_always') || !empty($result);
|
||||
|
||||
if (isset($cacheItem)) {
|
||||
if (isset($cacheItem) && $requireCache) {
|
||||
// 缓存数据
|
||||
$cacheItem->set($result);
|
||||
$this->cacheData($cacheItem);
|
||||
}
|
||||
|
||||
return false !== $result ? $result : $default;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到某个字段的值
|
||||
*
|
||||
* @param BaseQuery $query 查询对象
|
||||
* @param string $aggregate 聚合方法
|
||||
* @param mixed $field 字段名
|
||||
* @param bool $force 强制转为数字类型
|
||||
* @param BaseQuery $query 查询对象
|
||||
* @param string $aggregate 聚合方法
|
||||
* @param string|Raw $field 字段名
|
||||
* @param bool $force 强制转为数字类型
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function aggregate(BaseQuery $query, string $aggregate, $field, bool $force = false, bool $one = true)
|
||||
public function aggregate(BaseQuery $query, string $aggregate, string | Raw $field, bool $force = false)
|
||||
{
|
||||
if (is_string($field) && 0 === stripos($field, 'DISTINCT ')) {
|
||||
[$distinct, $field] = explode(' ', $field);
|
||||
@ -1280,7 +1285,7 @@ abstract class PDOConnection extends Connection
|
||||
|
||||
$field = $aggregate . '(' . (!empty($distinct) ? 'DISTINCT ' : '') . $this->builder->parseKey($query, $field, true) . ') AS think_' . strtolower($aggregate);
|
||||
|
||||
$result = $this->value($query, $field, 0, $one);
|
||||
$result = $this->value($query, $field, 0, false);
|
||||
|
||||
return $force ? (float) $result : $result;
|
||||
}
|
||||
@ -1294,7 +1299,7 @@ abstract class PDOConnection extends Connection
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function column(BaseQuery $query, string|array $column, string $key = ''): array
|
||||
public function column(BaseQuery $query, string | array $column, string $key = ''): array
|
||||
{
|
||||
$options = $query->parseOptions();
|
||||
|
||||
@ -1329,7 +1334,10 @@ abstract class PDOConnection extends Connection
|
||||
$name = $cacheItem->getKey();
|
||||
|
||||
if ($this->cache->has($name)) {
|
||||
return $this->cache->get($name);
|
||||
$data = $this->cache->get($name);
|
||||
if (null !== $data) {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1344,7 +1352,7 @@ abstract class PDOConnection extends Connection
|
||||
}
|
||||
|
||||
// 执行查询操作
|
||||
$pdo = $this->getPDOStatement($sql, $query->getBind(), $options['master']);
|
||||
$pdo = $this->getPDOStatement($sql, $query->getBind(), $options['master']);
|
||||
$resultSet = $pdo->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if (is_string($key) && str_contains($key, '.')) {
|
||||
@ -1374,7 +1382,9 @@ abstract class PDOConnection extends Connection
|
||||
$result = $resultSet;
|
||||
}
|
||||
|
||||
if (isset($cacheItem)) {
|
||||
$requireCache = $query->getOptions('cache_always') || !empty($result);
|
||||
|
||||
if (isset($cacheItem) && $requireCache) {
|
||||
// 缓存数据
|
||||
$cacheItem->set($result);
|
||||
$this->cacheData($cacheItem);
|
||||
@ -1516,15 +1526,12 @@ abstract class PDOConnection extends Connection
|
||||
$this->startTrans();
|
||||
|
||||
try {
|
||||
$result = null;
|
||||
if (is_callable($callback)) {
|
||||
$result = $callback($this);
|
||||
}
|
||||
$result = $callback($this);
|
||||
|
||||
$this->commit();
|
||||
|
||||
return $result;
|
||||
} catch (\Exception | \Throwable $e) {
|
||||
} catch (\Exception | \Throwable $e) {
|
||||
$this->rollback();
|
||||
|
||||
throw $e;
|
||||
@ -1544,19 +1551,17 @@ abstract class PDOConnection extends Connection
|
||||
try {
|
||||
$this->initConnect(true);
|
||||
|
||||
$this->transTimes++;
|
||||
|
||||
if (1 == $this->transTimes) {
|
||||
if (0 == $this->transTimes) {
|
||||
$this->linkID->beginTransaction();
|
||||
} elseif ($this->transTimes > 1 && $this->supportSavepoint() && $this->linkID->inTransaction()) {
|
||||
} elseif ($this->transTimes > 0 && $this->supportSavepoint() && $this->linkID->inTransaction()) {
|
||||
$this->linkID->exec(
|
||||
$this->parseSavepoint('trans' . $this->transTimes)
|
||||
$this->parseSavepoint('trans' . ($this->transTimes + 1))
|
||||
);
|
||||
}
|
||||
$this->transTimes++;
|
||||
$this->reConnectTimes = 0;
|
||||
} catch (\Throwable | \Exception $e) {
|
||||
if (1 === $this->transTimes && $this->reConnectTimes < 4 && $this->isBreak($e)) {
|
||||
$this->transTimes--;
|
||||
} catch (\Throwable | \Exception $e) {
|
||||
if (0 === $this->transTimes && $this->reConnectTimes < 4 && $this->isBreak($e)) {
|
||||
$this->reConnectTimes++;
|
||||
$this->close()->startTrans();
|
||||
} else {
|
||||
@ -1580,12 +1585,11 @@ abstract class PDOConnection extends Connection
|
||||
public function commit(): void
|
||||
{
|
||||
$this->initConnect(true);
|
||||
$this->transTimes = max(0, $this->transTimes - 1);
|
||||
|
||||
if (1 == $this->transTimes && $this->linkID->inTransaction()) {
|
||||
if (0 == $this->transTimes && $this->linkID->inTransaction()) {
|
||||
$this->linkID->commit();
|
||||
}
|
||||
|
||||
$this->transTimes--;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1598,18 +1602,17 @@ abstract class PDOConnection extends Connection
|
||||
public function rollback(): void
|
||||
{
|
||||
$this->initConnect(true);
|
||||
$this->transTimes = max(0, $this->transTimes - 1);
|
||||
|
||||
if ($this->linkID->inTransaction()) {
|
||||
if (1 == $this->transTimes) {
|
||||
if (0 == $this->transTimes) {
|
||||
$this->linkID->rollBack();
|
||||
} elseif ($this->transTimes > 1 && $this->supportSavepoint()) {
|
||||
} elseif ($this->transTimes > 0 && $this->supportSavepoint()) {
|
||||
$this->linkID->exec(
|
||||
$this->parseSavepointRollBack('trans' . $this->transTimes)
|
||||
$this->parseSavepointRollBack('trans' . ($this->transTimes + 1))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->transTimes = max(0, $this->transTimes - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1682,10 +1685,10 @@ abstract class PDOConnection extends Connection
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
$this->linkID = null;
|
||||
$this->linkWrite = null;
|
||||
$this->linkRead = null;
|
||||
$this->links = [];
|
||||
$this->linkID = null;
|
||||
$this->linkWrite = null;
|
||||
$this->linkRead = null;
|
||||
$this->links = [];
|
||||
$this->transTimes = 0;
|
||||
|
||||
$this->free();
|
||||
@ -1735,7 +1738,7 @@ abstract class PDOConnection extends Connection
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLastInsID(BaseQuery $query, string $sequence = null)
|
||||
public function getLastInsID(BaseQuery $query, ?string $sequence = null)
|
||||
{
|
||||
try {
|
||||
$insertId = $this->linkID->lastInsertId($sequence);
|
||||
@ -1758,7 +1761,7 @@ abstract class PDOConnection extends Connection
|
||||
{
|
||||
$pk = $query->getAutoInc();
|
||||
|
||||
if ($pk) {
|
||||
if ($pk && is_string($pk)) {
|
||||
$type = $this->getFieldsBind($query->getTable())[$pk];
|
||||
|
||||
if (self::PARAM_INT == $type) {
|
||||
@ -1843,7 +1846,8 @@ abstract class PDOConnection extends Connection
|
||||
|
||||
if ($this->config['rw_separate']) {
|
||||
// 主从式采用读写分离
|
||||
if ($master) { // 主服务器写入
|
||||
if ($master) {
|
||||
// 主服务器写入
|
||||
$r = $m;
|
||||
} elseif (is_numeric($this->config['slave_no'])) {
|
||||
// 指定服务器读
|
||||
@ -1917,10 +1921,7 @@ abstract class PDOConnection extends Connection
|
||||
}
|
||||
|
||||
try {
|
||||
$result = null;
|
||||
if (is_callable($callback)) {
|
||||
$result = $callback($this);
|
||||
}
|
||||
$result = $callback($this);
|
||||
|
||||
foreach ($dbs as $db) {
|
||||
$db->prepareXa($db->getUniqueXid('_' . $xid));
|
||||
@ -1931,7 +1932,7 @@ abstract class PDOConnection extends Connection
|
||||
}
|
||||
|
||||
return $result;
|
||||
} catch (\Exception | \Throwable $e) {
|
||||
} catch (\Exception | \Throwable $e) {
|
||||
foreach ($dbs as $db) {
|
||||
$db->rollbackXa($db->getUniqueXid('_' . $xid));
|
||||
}
|
||||
|
||||
55
vendor/topthink/think-orm/src/db/Query.php
vendored
Executable file → Normal file
55
vendor/topthink/think-orm/src/db/Query.php
vendored
Executable file → Normal file
@ -9,11 +9,13 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db;
|
||||
|
||||
use Closure;
|
||||
use PDOStatement;
|
||||
use ReflectionFunction;
|
||||
use think\db\exception\DbException as Exception;
|
||||
|
||||
/**
|
||||
@ -392,12 +394,12 @@ class Query extends BaseQuery
|
||||
* 字段值增长(支持延迟写入)
|
||||
*
|
||||
* @param string $field 字段名
|
||||
* @param int $step 步进值
|
||||
* @param float $step 步进值
|
||||
* @param int $lazyTime 延迟时间(秒)
|
||||
*
|
||||
* @return int|false
|
||||
*/
|
||||
public function setInc(string $field, int $step = 1, $lazyTime = 0)
|
||||
public function setInc(string $field, float $step = 1, int $lazyTime = 0)
|
||||
{
|
||||
if (empty($this->options['where']) && $this->model) {
|
||||
$this->where($this->model->getWhere());
|
||||
@ -423,12 +425,12 @@ class Query extends BaseQuery
|
||||
* 字段值减少(支持延迟写入)
|
||||
*
|
||||
* @param string $field 字段名
|
||||
* @param int $step 步进值
|
||||
* @param float $step 步进值
|
||||
* @param int $lazyTime 延迟时间(秒)
|
||||
*
|
||||
* @return int|false
|
||||
*/
|
||||
public function setDec(string $field, int $step = 1, int $lazyTime = 0)
|
||||
public function setDec(string $field, float $step = 1, int $lazyTime = 0)
|
||||
{
|
||||
if (empty($this->options['where']) && $this->model) {
|
||||
$this->where($this->model->getWhere());
|
||||
@ -457,11 +459,11 @@ class Query extends BaseQuery
|
||||
* @access protected
|
||||
* @param string $type 自增或者自减
|
||||
* @param string $guid 写入标识
|
||||
* @param int $step 写入步进值
|
||||
* @param float $step 写入步进值
|
||||
* @param int $lazyTime 延时时间(s)
|
||||
* @return false|integer
|
||||
*/
|
||||
protected function lazyWrite(string $type, string $guid, int $step, int $lazyTime)
|
||||
protected function lazyWrite(string $type, string $guid, float $step, int $lazyTime)
|
||||
{
|
||||
$cache = $this->getCache();
|
||||
if (!$cache->has($guid . '_time')) {
|
||||
@ -517,7 +519,30 @@ class Query extends BaseQuery
|
||||
*/
|
||||
public function getQueryGuid($data = null): string
|
||||
{
|
||||
return md5($this->getConfig('database') . serialize(var_export($data ?: $this->options, true)) . serialize($this->getBind(false)));
|
||||
if (null === $data) {
|
||||
$data = $this->options;
|
||||
$data['table'] = $this->getConfig('database') . var_export($this->getTable(), true);
|
||||
unset($data['scope'], $data['default_model']);
|
||||
foreach (['AND', 'OR', 'XOR'] as $logic) {
|
||||
if (isset($data['where'][$logic])) {
|
||||
foreach ($data['where'][$logic] as $key => $val) {
|
||||
if ($val instanceof Closure) {
|
||||
$reflection = new ReflectionFunction($val);
|
||||
$properties = $reflection->getStaticVariables();
|
||||
if (empty($properties)) {
|
||||
$name = $reflection->getName() . $reflection->getStartLine() . '-' . $reflection->getEndLine();
|
||||
} else {
|
||||
$name = var_export($properties, true);
|
||||
}
|
||||
$data['Closure'][] = $name;
|
||||
unset($data['where'][$logic][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return md5(serialize(var_export($data, true)) . serialize($this->getBind(false)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -554,19 +579,19 @@ class Query extends BaseQuery
|
||||
/**
|
||||
* 分批数据返回处理.
|
||||
*
|
||||
* @param int $count 每次处理的数据数量
|
||||
* @param callable $callback 处理回调方法
|
||||
* @param string|array $column 分批处理的字段名
|
||||
* @param string $order 字段排序
|
||||
* @param int $count 每次处理的数据数量
|
||||
* @param callable $callback 处理回调方法
|
||||
* @param string|array|null $column 分批处理的字段名
|
||||
* @param string $order 字段排序
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function chunk(int $count, callable $callback, string|array $column = null, string $order = 'asc'): bool
|
||||
public function chunk(int $count, callable $callback, string | array | null $column = null, string $order = 'asc'): bool
|
||||
{
|
||||
$options = $this->getOptions();
|
||||
$column = $column ?: $this->getPk();
|
||||
$column = $column ?: $this->getPk();
|
||||
|
||||
if (isset($options['order'])) {
|
||||
unset($options['order']);
|
||||
@ -598,7 +623,7 @@ class Query extends BaseQuery
|
||||
$times++;
|
||||
$query = $this->options($options)->page($times, $count);
|
||||
} else {
|
||||
$end = $resultSet->pop();
|
||||
$end = $resultSet->pop();
|
||||
$lastId = is_array($end) ? $end[$key] : $end->getData($key);
|
||||
|
||||
$query = $this->options($options)
|
||||
|
||||
2
vendor/topthink/think-orm/src/db/Raw.php
vendored
Executable file → Normal file
2
vendor/topthink/think-orm/src/db/Raw.php
vendored
Executable file → Normal file
@ -45,7 +45,7 @@ class Raw
|
||||
/**
|
||||
* 获取参数绑定.
|
||||
*
|
||||
* @return string
|
||||
* @return array
|
||||
*/
|
||||
public function getBind(): array
|
||||
{
|
||||
|
||||
2
vendor/topthink/think-orm/src/db/Where.php
vendored
Executable file → Normal file
2
vendor/topthink/think-orm/src/db/Where.php
vendored
Executable file → Normal file
@ -168,7 +168,7 @@ class Where implements ArrayAccess
|
||||
$this->__unset($name);
|
||||
}
|
||||
|
||||
public function offsetGet(mixed $name)
|
||||
public function offsetGet(mixed $name): mixed
|
||||
{
|
||||
return $this->__get($name);
|
||||
}
|
||||
|
||||
1
vendor/topthink/think-orm/src/db/builder/Mongo.php
vendored
Executable file → Normal file
1
vendor/topthink/think-orm/src/db/builder/Mongo.php
vendored
Executable file → Normal file
@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
50
vendor/topthink/think-orm/src/db/builder/Mysql.php
vendored
Executable file → Normal file
50
vendor/topthink/think-orm/src/db/builder/Mysql.php
vendored
Executable file → Normal file
@ -9,14 +9,14 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db\builder;
|
||||
|
||||
use PDO;
|
||||
use think\db\BaseQuery as Query;
|
||||
use think\db\Builder;
|
||||
use think\db\exception\DbException as Exception;
|
||||
use think\db\BaseQuery as Query;
|
||||
use think\db\Raw;
|
||||
|
||||
/**
|
||||
@ -30,7 +30,7 @@ class Mysql extends Builder
|
||||
* @var array
|
||||
*/
|
||||
protected $parser = [
|
||||
'parseCompare' => ['=', '<>', '>', '>=', '<', '<='],
|
||||
'parseCompare' => ['=', '!=', '<>', '>', '>=', '<', '<='],
|
||||
'parseLike' => ['LIKE', 'NOT LIKE'],
|
||||
'parseBetween' => ['NOT BETWEEN', 'BETWEEN'],
|
||||
'parseIn' => ['NOT IN', 'IN'],
|
||||
@ -161,8 +161,8 @@ class Mysql extends Builder
|
||||
*/
|
||||
public function insertAll(Query $query, array $dataSet): string
|
||||
{
|
||||
$options = $query->getOptions();
|
||||
$bind = $query->getFieldsBindType();
|
||||
$options = $query->getOptions();
|
||||
$bind = $query->getFieldsBindType();
|
||||
|
||||
// 获取合法的字段
|
||||
if (empty($options['field']) || '*' == $options['field']) {
|
||||
@ -215,9 +215,9 @@ class Mysql extends Builder
|
||||
public function insertAllByKeys(Query $query, array $keys, array $datas): string
|
||||
{
|
||||
$options = $query->getOptions();
|
||||
$bind = $query->getFieldsBindType();
|
||||
$fields = [];
|
||||
$values = [];
|
||||
$bind = $query->getFieldsBindType();
|
||||
$fields = [];
|
||||
$values = [];
|
||||
|
||||
foreach ($keys as $field) {
|
||||
$fields[] = $this->parseKey($query, $field);
|
||||
@ -259,8 +259,8 @@ class Mysql extends Builder
|
||||
*/
|
||||
public function update(Query $query): string
|
||||
{
|
||||
$options = $query->getOptions();
|
||||
$data = $this->parseData($query, $options['data']);
|
||||
$options = $query->getOptions();
|
||||
$data = $this->parseData($query, $options['data']);
|
||||
|
||||
if (empty($data)) {
|
||||
return '';
|
||||
@ -367,11 +367,13 @@ class Mysql extends Builder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function parseKey(Query $query, string|int|Raw $key, bool $strict = false): string
|
||||
public function parseKey(Query $query, string | int | Raw $key, bool $strict = false): string
|
||||
{
|
||||
if (is_int($key)) {
|
||||
return (string) $key;
|
||||
} elseif ($key instanceof Raw) {
|
||||
}
|
||||
|
||||
if ($key instanceof Raw) {
|
||||
return $this->parseRaw($query, $key);
|
||||
}
|
||||
|
||||
@ -382,12 +384,16 @@ class Mysql extends Builder
|
||||
[$field, $name] = explode('->>', $key, 2);
|
||||
|
||||
return $this->parseKey($query, $field, true) . '->>\'$' . (str_starts_with($name, '[') ? '' : '.') . str_replace('->>', '.', $name) . '\'';
|
||||
} elseif (str_contains($key, '->') && !str_contains($key, '(')) {
|
||||
}
|
||||
|
||||
if (str_contains($key, '->') && !str_contains($key, '(')) {
|
||||
// JSON字段支持
|
||||
[$field, $name] = explode('->', $key, 2);
|
||||
|
||||
return 'json_extract(' . $this->parseKey($query, $field, true) . ', \'$' . (str_starts_with($name, '[') ? '' : '.') . str_replace('->', '.', $name) . '\')';
|
||||
} elseif (str_contains($key, '.') && !preg_match('/[,\'\"\(\)`\s]/', $key)) {
|
||||
return 'json_unquote(json_extract(' . $this->parseKey($query, $field, true) . ', \'$' . (str_starts_with($name, '[') ? '' : '.') . str_replace('->', '.', $name) . '\'))';
|
||||
}
|
||||
|
||||
if (str_contains($key, '.') && !preg_match('/[,\'\"\(\)`\s]/', $key)) {
|
||||
[$table, $key] = explode('.', $key, 2);
|
||||
|
||||
$alias = $query->getOptions('alias');
|
||||
@ -435,11 +441,11 @@ class Mysql extends Builder
|
||||
*/
|
||||
protected function parseNull(Query $query, string $key, string $exp, $value, $field, int $bindType): string
|
||||
{
|
||||
if (str_starts_with($key, "json_extract")) {
|
||||
if ($exp === 'NULL') {
|
||||
return '(' . $key . ' is null OR json_type(' . $key . ') = \'NULL\')';
|
||||
}elseif ($exp === 'NOT NULL'){
|
||||
return '(' . $key . ' is not null AND json_type(' . $key . ') != \'NULL\')';
|
||||
if (str_starts_with($key, "json_unquote(json_extract")) {
|
||||
if ('NULL' === $exp) {
|
||||
return '(' . $key . ' is null OR ' . $key . ' = \'null\')';
|
||||
} elseif ('NOT NULL' === $exp) {
|
||||
return '(' . $key . ' is not null AND ' . $key . ' != \'null\')';
|
||||
}
|
||||
}
|
||||
|
||||
@ -504,12 +510,12 @@ class Mysql extends Builder
|
||||
$updates = [];
|
||||
foreach ($duplicate as $key => $val) {
|
||||
if (is_numeric($key)) {
|
||||
$val = $this->parseKey($query, $val);
|
||||
$val = $this->parseKey($query, $val);
|
||||
$updates[] = $val . ' = VALUES(' . $val . ')';
|
||||
} elseif ($val instanceof Raw) {
|
||||
$updates[] = $this->parseKey($query, $key) . ' = ' . $this->parseRaw($query, $val);
|
||||
} else {
|
||||
$name = $query->bindValue($val, $query->getConnection()->getFieldBindType($key));
|
||||
$name = $query->bindValue($val, $query->getConnection()->getFieldBindType($key));
|
||||
$updates[] = $this->parseKey($query, $key) . ' = :' . $name;
|
||||
}
|
||||
}
|
||||
|
||||
0
vendor/topthink/think-orm/src/db/builder/Oracle.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/builder/Oracle.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/builder/Pgsql.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/builder/Pgsql.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/builder/Sqlite.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/builder/Sqlite.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/builder/Sqlsrv.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/builder/Sqlsrv.php
vendored
Executable file → Normal file
71
vendor/topthink/think-orm/src/db/concern/AggregateQuery.php
vendored
Executable file → Normal file
71
vendor/topthink/think-orm/src/db/concern/AggregateQuery.php
vendored
Executable file → Normal file
@ -9,7 +9,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db\concern;
|
||||
|
||||
@ -30,9 +30,9 @@ trait AggregateQuery
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function aggregate(string $aggregate, string|Raw $field, bool $force = false, bool $one = false)
|
||||
protected function aggregate(string $aggregate, string | Raw $field, bool $force = false)
|
||||
{
|
||||
return $this->connection->aggregate($this, $aggregate, $field, $force, $one);
|
||||
return $this->connection->aggregate($this, $aggregate, $field, $force);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -45,35 +45,38 @@ trait AggregateQuery
|
||||
public function count(string $field = '*'): int
|
||||
{
|
||||
if (!empty($this->options['group'])) {
|
||||
// 支持GROUP
|
||||
|
||||
if (!preg_match('/^[\w\.\*]+$/', $field)) {
|
||||
throw new DbException('not support data:' . $field);
|
||||
}
|
||||
|
||||
$options = $this->getOptions();
|
||||
if (isset($options['cache'])) {
|
||||
$cache = $options['cache'];
|
||||
unset($options['cache']);
|
||||
}
|
||||
|
||||
$subSql = $this->options($options)
|
||||
->field('count(' . $field . ') AS think_count')
|
||||
->bind($this->bind)
|
||||
->buildSql();
|
||||
|
||||
$query = $this->newQuery();
|
||||
if (isset($cache)) {
|
||||
$query->setOption('cache', $cache);
|
||||
}
|
||||
$query->table([$subSql => '_group_count_']);
|
||||
|
||||
$count = $query->aggregate('COUNT', '*');
|
||||
} else {
|
||||
$count = $this->aggregate('COUNT', $field);
|
||||
return $this->countWithGroup($field);
|
||||
}
|
||||
|
||||
return (int) $count;
|
||||
return (int) $this->aggregate('COUNT', $field);
|
||||
}
|
||||
|
||||
protected function countWithGroup(string $field): int
|
||||
{
|
||||
if (!preg_match('/^[\w\.\*]+$/', $field)) {
|
||||
throw new DbException('Not supported data: ' . $field);
|
||||
}
|
||||
|
||||
$options = $this->getOptions();
|
||||
$cache = $options['cache'] ?? null;
|
||||
|
||||
if (isset($options['cache'])) {
|
||||
unset($options['cache']);
|
||||
}
|
||||
|
||||
$subSql = $this->options($options)
|
||||
->field('count(' . $field . ') AS think_count')
|
||||
->bind($this->bind)
|
||||
->buildSql();
|
||||
|
||||
$query = $this->newQuery();
|
||||
if ($cache) {
|
||||
$query->setOption('cache', $cache);
|
||||
}
|
||||
|
||||
$query->table([$subSql => '_group_count_']);
|
||||
|
||||
return (int) $query->aggregate('COUNT', '*');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,7 +86,7 @@ trait AggregateQuery
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function sum(string|Raw $field): float
|
||||
public function sum(string | Raw $field): float
|
||||
{
|
||||
return $this->aggregate('SUM', $field, true);
|
||||
}
|
||||
@ -96,7 +99,7 @@ trait AggregateQuery
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function min(string|Raw $field, bool $force = true)
|
||||
public function min(string | Raw $field, bool $force = true)
|
||||
{
|
||||
return $this->aggregate('MIN', $field, $force);
|
||||
}
|
||||
@ -109,7 +112,7 @@ trait AggregateQuery
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function max(string|Raw $field, bool $force = true)
|
||||
public function max(string | Raw $field, bool $force = true)
|
||||
{
|
||||
return $this->aggregate('MAX', $field, $force);
|
||||
}
|
||||
@ -121,7 +124,7 @@ trait AggregateQuery
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function avg(string|Raw $field): float
|
||||
public function avg(string | Raw $field): float
|
||||
{
|
||||
return $this->aggregate('AVG', $field, true);
|
||||
}
|
||||
|
||||
147
vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php
vendored
Executable file → Normal file
147
vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php
vendored
Executable file → Normal file
@ -9,11 +9,12 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db\concern;
|
||||
|
||||
use think\db\Raw;
|
||||
use think\helper\Str;
|
||||
|
||||
/**
|
||||
* JOIN和VIEW查询.
|
||||
@ -30,7 +31,7 @@ trait JoinAndViewQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function join(array|string|Raw $join, string $condition = null, string $type = 'INNER', array $bind = [])
|
||||
public function join(array | string | Raw $join, ?string $condition = null, string $type = 'INNER', array $bind = [])
|
||||
{
|
||||
$table = $this->getJoinTable($join);
|
||||
|
||||
@ -52,7 +53,7 @@ trait JoinAndViewQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function leftJoin(array|string|Raw $join, string $condition = null, array $bind = [])
|
||||
public function leftJoin(array | string | Raw $join, ?string $condition = null, array $bind = [])
|
||||
{
|
||||
return $this->join($join, $condition, 'LEFT', $bind);
|
||||
}
|
||||
@ -66,7 +67,7 @@ trait JoinAndViewQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function rightJoin(array|string|Raw $join, string $condition = null, array $bind = [])
|
||||
public function rightJoin(array | string | Raw $join, ?string $condition = null, array $bind = [])
|
||||
{
|
||||
return $this->join($join, $condition, 'RIGHT', $bind);
|
||||
}
|
||||
@ -80,9 +81,9 @@ trait JoinAndViewQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function fullJoin(array|string|Raw $join, string $condition = null, array $bind = [])
|
||||
public function fullJoin(array | string | Raw $join, ?string $condition = null, array $bind = [])
|
||||
{
|
||||
return $this->join($join, $condition, 'FULL');
|
||||
return $this->join($join, $condition, 'FULL', $bind);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,37 +95,34 @@ trait JoinAndViewQuery
|
||||
*
|
||||
* @return string|array
|
||||
*/
|
||||
protected function getJoinTable(array|string|Raw $join, string &$alias = null)
|
||||
protected function getJoinTable(array | string | Raw $join, ?string &$alias = null)
|
||||
{
|
||||
if (is_array($join)) {
|
||||
$table = $join;
|
||||
$alias = array_shift($join);
|
||||
|
||||
return $table;
|
||||
} elseif ($join instanceof Raw) {
|
||||
}
|
||||
|
||||
if ($join instanceof Raw || str_contains($join, '(')) {
|
||||
return $join;
|
||||
}
|
||||
|
||||
$join = trim($join);
|
||||
|
||||
if (str_contains($join, '(')) {
|
||||
// 使用子查询
|
||||
$table = $join;
|
||||
} else {
|
||||
// 使用别名
|
||||
if (str_contains($join, ' ')) {
|
||||
// 使用别名
|
||||
if (str_contains($join, ' ')) {
|
||||
// 使用别名
|
||||
[$table, $alias] = explode(' ', $join);
|
||||
} else {
|
||||
$table = $join;
|
||||
if (!str_contains($join, '.')) {
|
||||
$alias = $join;
|
||||
}
|
||||
[$table, $alias] = explode(' ', $join);
|
||||
} else {
|
||||
$table = $join;
|
||||
if (!str_contains($join, '.')) {
|
||||
$alias = $join;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->prefix && !str_contains($table, '.') && !str_starts_with($table, $this->prefix)) {
|
||||
$table = $this->getTable($table);
|
||||
}
|
||||
if ($this->prefix && !str_contains($table, '.') && !str_starts_with($table, $this->prefix)) {
|
||||
$table = $this->prefix . Str::snake($table) . $this->suffix;
|
||||
}
|
||||
|
||||
if (!empty($alias) && $table != $alias) {
|
||||
@ -145,41 +143,19 @@ trait JoinAndViewQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function view(array|string|Raw $join, string|array|bool $field = true, string $on = null, string $type = 'INNER', array $bind = [])
|
||||
public function view(array | string | Raw $join, string | array | bool $field = true, ?string $on = null, string $type = 'INNER', array $bind = []): self
|
||||
{
|
||||
$this->options['view'] = true;
|
||||
|
||||
$fields = [];
|
||||
$table = $this->getJoinTable($join, $alias);
|
||||
$table = $this->getJoinTable($join, $alias);
|
||||
|
||||
if (true === $field) {
|
||||
$fields = $alias . '.*';
|
||||
} else {
|
||||
if (is_string($field)) {
|
||||
$field = explode(',', $field);
|
||||
}
|
||||
|
||||
foreach ($field as $key => $val) {
|
||||
if (is_numeric($key)) {
|
||||
$fields[] = $alias . '.' . $val;
|
||||
|
||||
$this->options['map'][$val] = $alias . '.' . $val;
|
||||
} else {
|
||||
if (preg_match('/[,=\.\'\"\(\s]/', $key)) {
|
||||
$name = $key;
|
||||
} else {
|
||||
$name = $alias . '.' . $key;
|
||||
}
|
||||
|
||||
$fields[] = $name . ' AS ' . $val;
|
||||
|
||||
$this->options['map'][$val] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理字段
|
||||
$fields = $this->processFields($field, $alias);
|
||||
|
||||
$this->field($fields);
|
||||
|
||||
// 处理连接
|
||||
if ($on) {
|
||||
$this->join($table, $on, $type, $bind);
|
||||
} else {
|
||||
@ -189,6 +165,28 @@ trait JoinAndViewQuery
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function processFields(string | array | bool $field, string $alias): array
|
||||
{
|
||||
$fields = [];
|
||||
|
||||
if (true === $field) {
|
||||
$fields[] = $alias . '.*'; // 选取所有字段
|
||||
} else {
|
||||
if (is_string($field)) {
|
||||
$field = explode(',', $field);
|
||||
}
|
||||
|
||||
foreach ($field as $key => $val) {
|
||||
$name = is_numeric($key) ? $alias . '.' . $val : (preg_match('/[,=\.\'\"\(\s]/', $key) ? $key : $alias . '.' . $key);
|
||||
$fields[] = $name . (is_numeric($key) ? '' : ' AS ' . $val);
|
||||
|
||||
$this->options['map'][$val] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 视图查询处理.
|
||||
*
|
||||
@ -199,36 +197,41 @@ trait JoinAndViewQuery
|
||||
protected function parseView(array &$options): void
|
||||
{
|
||||
foreach (['AND', 'OR'] as $logic) {
|
||||
if (isset($options['where'][$logic])) {
|
||||
foreach ($options['where'][$logic] as $key => $val) {
|
||||
if (array_key_exists($key, $options['map'])) {
|
||||
array_shift($val);
|
||||
array_unshift($val, $options['map'][$key]);
|
||||
$options['where'][$logic][$options['map'][$key]] = $val;
|
||||
unset($options['where'][$logic][$key]);
|
||||
}
|
||||
if (!isset($options['where'][$logic])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 视图查询条件处理
|
||||
foreach ($options['where'][$logic] as $key => $val) {
|
||||
if (array_key_exists($key, $options['map'])) {
|
||||
array_shift($val);
|
||||
array_unshift($val, $options['map'][$key]);
|
||||
$options['where'][$logic][$options['map'][$key]] = $val;
|
||||
unset($options['where'][$logic][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($options['order'])) {
|
||||
// 视图查询排序处理
|
||||
foreach ($options['order'] as $key => $val) {
|
||||
if (is_numeric($key) && is_string($val)) {
|
||||
if (str_contains($val, ' ')) {
|
||||
[$field, $sort] = explode(' ', $val);
|
||||
if (array_key_exists($field, $options['map'])) {
|
||||
$options['order'][$options['map'][$field]] = $sort;
|
||||
unset($options['order'][$key]);
|
||||
}
|
||||
} elseif (array_key_exists($val, $options['map'])) {
|
||||
$options['order'][$options['map'][$val]] = 'asc';
|
||||
if (empty($options['order'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 视图查询排序处理
|
||||
foreach ($options['order'] as $key => $val) {
|
||||
if (is_numeric($key) && is_string($val)) {
|
||||
if (str_contains($val, ' ')) {
|
||||
[$field, $sort] = explode(' ', $val);
|
||||
if (array_key_exists($field, $options['map'])) {
|
||||
$options['order'][$options['map'][$field]] = $sort;
|
||||
unset($options['order'][$key]);
|
||||
}
|
||||
} elseif (array_key_exists($key, $options['map'])) {
|
||||
$options['order'][$options['map'][$key]] = $val;
|
||||
} elseif (array_key_exists($val, $options['map'])) {
|
||||
$options['order'][$options['map'][$val]] = 'asc';
|
||||
unset($options['order'][$key]);
|
||||
}
|
||||
} elseif (array_key_exists($key, $options['map'])) {
|
||||
$options['order'][$options['map'][$key]] = $val;
|
||||
unset($options['order'][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
169
vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php
vendored
Executable file → Normal file
169
vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php
vendored
Executable file → Normal file
@ -9,7 +9,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db\concern;
|
||||
|
||||
@ -58,12 +58,13 @@ trait ModelRelationQuery
|
||||
* 设置需要隐藏的输出属性.
|
||||
*
|
||||
* @param array $hidden 属性列表
|
||||
* @param bool $merge 是否合并
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function hidden(array $hidden = [])
|
||||
public function hidden(array $hidden, bool $merge = false)
|
||||
{
|
||||
$this->options['hidden'] = $hidden;
|
||||
$this->options['hidden'] = [$hidden, $merge];
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -71,13 +72,14 @@ trait ModelRelationQuery
|
||||
/**
|
||||
* 设置需要输出的属性.
|
||||
*
|
||||
* @param array $visible
|
||||
* @param array $visible 属性列表
|
||||
* @param bool $merge 是否合并
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function visible(array $visible = [])
|
||||
public function visible(array $visible, bool $merge = false)
|
||||
{
|
||||
$this->options['visible'] = $visible;
|
||||
$this->options['visible'] = [$visible, $merge];
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -86,12 +88,27 @@ trait ModelRelationQuery
|
||||
* 设置需要附加的输出属性.
|
||||
*
|
||||
* @param array $append 属性列表
|
||||
* @param bool $merge 是否合并
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function append(array $append = [])
|
||||
public function append(array $append, bool $merge = false)
|
||||
{
|
||||
$this->options['append'] = $append;
|
||||
$this->options['append'] = [$append, $merge];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置模型的输出映射.
|
||||
*
|
||||
* @param array $mapping 映射列表
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function mapping(array $mapping)
|
||||
{
|
||||
$this->options['mapping'] = $mapping;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -110,22 +127,20 @@ trait ModelRelationQuery
|
||||
array_unshift($args, $this);
|
||||
|
||||
if ($scope instanceof Closure) {
|
||||
call_user_func_array($scope, $args);
|
||||
|
||||
$this->options['scope'][] = [$scope, $args];
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (is_string($scope)) {
|
||||
$scope = explode(',', $scope);
|
||||
}
|
||||
|
||||
if ($this->model) {
|
||||
if (is_string($scope)) {
|
||||
$scope = explode(',', $scope);
|
||||
}
|
||||
|
||||
// 检查模型类的查询范围方法
|
||||
foreach ($scope as $name) {
|
||||
$method = 'scope' . trim($name);
|
||||
|
||||
if (method_exists($this->model, $method)) {
|
||||
call_user_func_array([$this->model, $method], $args);
|
||||
$this->options['scope'][$name] = [[$this->model, $method], $args];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -133,6 +148,46 @@ trait ModelRelationQuery
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行查询范围查询.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function scopeQuery()
|
||||
{
|
||||
if (!empty($this->options['scope'])) {
|
||||
foreach ($this->options['scope'] as $val) {
|
||||
[$call, $args] = $val;
|
||||
call_user_func_array($call, $args);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定不使用的查询范围.
|
||||
*
|
||||
* @param array $scope 查询范围
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withoutScope(array $scope = [])
|
||||
{
|
||||
if (empty($scope)) {
|
||||
$this->options['scope'] = [];
|
||||
return $this;
|
||||
}
|
||||
|
||||
foreach ($scope as $name) {
|
||||
if (isset($this->options['scope'][$name])) {
|
||||
unset($this->options['scope'][$name]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置关联查询.
|
||||
*
|
||||
@ -156,11 +211,11 @@ trait ModelRelationQuery
|
||||
*
|
||||
* @param string|array $fields 搜索字段
|
||||
* @param mixed $data 搜索数据
|
||||
* @param string $prefix 字段前缀标识
|
||||
* @param bool $strict 是否严格检查数据
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withSearch($fields, $data = [], string $prefix = '')
|
||||
public function withSearch($fields, $data = [], bool $strict = true)
|
||||
{
|
||||
if (is_string($fields)) {
|
||||
$fields = explode(',', $fields);
|
||||
@ -170,14 +225,17 @@ trait ModelRelationQuery
|
||||
|
||||
foreach ($fields as $key => $field) {
|
||||
if ($field instanceof Closure) {
|
||||
$field($this, $data[$key] ?? null, $data, $prefix);
|
||||
$field($this, $data[$key] ?? null, $data);
|
||||
} elseif ($this->model) {
|
||||
// 检测搜索器
|
||||
$fieldName = is_numeric($key) ? $field : $key;
|
||||
$method = 'search' . Str::studly($fieldName) . 'Attr';
|
||||
// 检查字段是否有数据
|
||||
if ($strict && (!isset($data[$field]) || (empty($data[$field]) && !in_array($data[$field], ['0', 0])))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fieldName = is_numeric($key) ? $field : $key;
|
||||
$method = 'search' . Str::studly($fieldName) . 'Attr';
|
||||
if (method_exists($this->model, $method)) {
|
||||
$this->model->$method($this, $data[$field] ?? null, $data, $prefix);
|
||||
$this->model->$method($this, $data[$field], $data);
|
||||
} elseif (isset($data[$field])) {
|
||||
$this->where($fieldName, in_array($fieldName, $likeFields) ? 'like' : '=', in_array($fieldName, $likeFields) ? '%' . $data[$field] . '%' : $data[$field]);
|
||||
}
|
||||
@ -229,6 +287,19 @@ trait ModelRelationQuery
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置关联模型的动态绑定
|
||||
*
|
||||
* @param array $attr 绑定数据
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withBind(array $attr)
|
||||
{
|
||||
$this->options['bind_attr'] = $attr;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置数据字段获取器.
|
||||
*
|
||||
@ -237,7 +308,7 @@ trait ModelRelationQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withAttr(string|array $name, callable $callback = null)
|
||||
public function withAttr(string | array $name, ?callable $callback = null)
|
||||
{
|
||||
if (is_array($name)) {
|
||||
foreach ($name as $key => $val) {
|
||||
@ -269,7 +340,7 @@ trait ModelRelationQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function with(array|string $with)
|
||||
public function with(array | string $with)
|
||||
{
|
||||
if (empty($this->model) || empty($with)) {
|
||||
return $this;
|
||||
@ -288,25 +359,25 @@ trait ModelRelationQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withJoin(array|string $with, string $joinType = '')
|
||||
public function withJoin(array | string $with, string $joinType = '')
|
||||
{
|
||||
if (empty($this->model) || empty($with)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$with = (array) $with;
|
||||
$with = (array) $with;
|
||||
$first = true;
|
||||
|
||||
foreach ($with as $key => $relation) {
|
||||
$closure = null;
|
||||
$field = true;
|
||||
$field = true;
|
||||
|
||||
if ($relation instanceof Closure) {
|
||||
// 支持闭包查询过滤关联条件
|
||||
$closure = $relation;
|
||||
$closure = $relation;
|
||||
$relation = $key;
|
||||
} elseif (is_array($relation)) {
|
||||
$field = $relation;
|
||||
$field = $relation;
|
||||
$relation = $key;
|
||||
} elseif (is_string($relation) && str_contains($relation, '.')) {
|
||||
$relation = strstr($relation, '.', true);
|
||||
@ -337,7 +408,7 @@ trait ModelRelationQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function withAggregate(string|array $relations, string $aggregate = 'count', $field = '*', bool $subQuery = true)
|
||||
protected function withAggregate(string | array $relations, string $aggregate = 'count', $field = '*', bool $subQuery = true)
|
||||
{
|
||||
if (empty($this->model)) {
|
||||
return $this;
|
||||
@ -368,7 +439,7 @@ trait ModelRelationQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withCache(string|array|bool $relation = true, $key = true, $expire = null, string $tag = null)
|
||||
public function withCache(string | array | bool $relation = true, $key = true, $expire = null, ?string $tag = null)
|
||||
{
|
||||
if (empty($this->model)) {
|
||||
return $this;
|
||||
@ -378,9 +449,9 @@ trait ModelRelationQuery
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($key instanceof \DateTimeInterface || $key instanceof \DateInterval || (is_int($key) && is_null($expire))) {
|
||||
if ($key instanceof \DateTimeInterface || $key instanceof \DateInterval || (is_int($key) && is_null($expire))) {
|
||||
$expire = $key;
|
||||
$key = true;
|
||||
$key = true;
|
||||
}
|
||||
|
||||
if (true === $relation || is_numeric($relation)) {
|
||||
@ -409,7 +480,7 @@ trait ModelRelationQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withCount(string|array $relation, bool $subQuery = true)
|
||||
public function withCount(string | array $relation, bool $subQuery = true)
|
||||
{
|
||||
return $this->withAggregate($relation, 'count', '*', $subQuery);
|
||||
}
|
||||
@ -423,7 +494,7 @@ trait ModelRelationQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withSum(string|array $relation, string $field, bool $subQuery = true)
|
||||
public function withSum(string | array $relation, string $field, bool $subQuery = true)
|
||||
{
|
||||
return $this->withAggregate($relation, 'sum', $field, $subQuery);
|
||||
}
|
||||
@ -437,7 +508,7 @@ trait ModelRelationQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withMax(string|array $relation, string $field, bool $subQuery = true)
|
||||
public function withMax(string | array $relation, string $field, bool $subQuery = true)
|
||||
{
|
||||
return $this->withAggregate($relation, 'max', $field, $subQuery);
|
||||
}
|
||||
@ -451,7 +522,7 @@ trait ModelRelationQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withMin(string|array $relation, string $field, bool $subQuery = true)
|
||||
public function withMin(string | array $relation, string $field, bool $subQuery = true)
|
||||
{
|
||||
return $this->withAggregate($relation, 'min', $field, $subQuery);
|
||||
}
|
||||
@ -465,7 +536,7 @@ trait ModelRelationQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withAvg(string|array $relation, string $field, bool $subQuery = true)
|
||||
public function withAvg(string | array $relation, string $field, bool $subQuery = true)
|
||||
{
|
||||
return $this->withAggregate($relation, 'avg', $field, $subQuery);
|
||||
}
|
||||
@ -517,6 +588,9 @@ trait ModelRelationQuery
|
||||
}
|
||||
|
||||
$jsonData = json_decode($result[$name], true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($withAttr[$name])) {
|
||||
foreach ($withAttr[$name] as $key => $closure) {
|
||||
@ -583,7 +657,9 @@ trait ModelRelationQuery
|
||||
if (!empty($this->options['lazy_fields'])) {
|
||||
$id = $this->getKey($result);
|
||||
foreach ($this->options['lazy_fields'] as $field) {
|
||||
$result[$field] += $this->getLazyFieldValue($field, $id);
|
||||
if (isset($result[$field])) {
|
||||
$result[$field] += $this->getLazyFieldValue($field, $id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -593,6 +669,10 @@ trait ModelRelationQuery
|
||||
$this->options
|
||||
);
|
||||
|
||||
if ($this->suffix) {
|
||||
$result->setSuffix($this->suffix);
|
||||
}
|
||||
|
||||
// 模型数据处理
|
||||
foreach ($this->options['filter'] as $filter) {
|
||||
call_user_func_array($filter, [$result, $this->options]);
|
||||
@ -626,12 +706,17 @@ trait ModelRelationQuery
|
||||
|
||||
// 动态获取器
|
||||
if (!empty($this->options['with_attr'])) {
|
||||
$result->withAttr($this->options['with_attr']);
|
||||
$result->withFieldAttr($this->options['with_attr']);
|
||||
}
|
||||
|
||||
if (!empty($this->options['mapping'])) {
|
||||
$result->mapping($this->options['mapping']);
|
||||
}
|
||||
|
||||
foreach (['hidden', 'visible', 'append'] as $name) {
|
||||
if (!empty($this->options[$name])) {
|
||||
$result->$name($this->options[$name]);
|
||||
[$value, $merge] = $this->options[$name];
|
||||
$result->$name($value, $merge);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
11
vendor/topthink/think-orm/src/db/concern/ParamsBind.php
vendored
Executable file → Normal file
11
vendor/topthink/think-orm/src/db/concern/ParamsBind.php
vendored
Executable file → Normal file
@ -9,7 +9,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db\concern;
|
||||
|
||||
@ -50,7 +50,7 @@ trait ParamsBind
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function bindValue($value, int $type = null, string $name = null)
|
||||
public function bindValue($value, ?int $type = null, ?string $name = null)
|
||||
{
|
||||
$name = $name ?: 'ThinkBind_' . (count($this->bind) + 1) . '_' . mt_rand() . '_';
|
||||
|
||||
@ -119,8 +119,13 @@ trait ParamsBind
|
||||
|
||||
if (is_numeric($key)) {
|
||||
$sql = substr_replace($sql, ':' . $name, strpos($sql, '?'), 1);
|
||||
} elseif (str_ends_with($sql, ':' . $key)) {
|
||||
$sql = substr_replace($sql, ':' . $name . ' ', strrpos($sql, ':' . $key), strlen(':' . $key));
|
||||
} else {
|
||||
$sql = str_replace(':' . $key, ':' . $name, $sql);
|
||||
$sql = str_replace(
|
||||
[':' . $key . ' ', ':' . $key . ',', ':' . $key . ')'],
|
||||
[':' . $name . ' ', ':' . $name . ',', ':' . $name . ')'],
|
||||
$sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
vendor/topthink/think-orm/src/db/concern/ResultOperation.php
vendored
Executable file → Normal file
24
vendor/topthink/think-orm/src/db/concern/ResultOperation.php
vendored
Executable file → Normal file
@ -9,7 +9,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db\concern;
|
||||
|
||||
@ -35,7 +35,7 @@ trait ResultOperation
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function filter(callable $filter, string $index = null)
|
||||
public function filter(callable $filter, ?string $index = null)
|
||||
{
|
||||
if ($index) {
|
||||
$this->options['filter'][$index] = $filter;
|
||||
@ -105,6 +105,16 @@ trait ResultOperation
|
||||
if (!empty($this->options['with_attr'])) {
|
||||
$this->getResultAttr($result, $this->options['with_attr']);
|
||||
}
|
||||
|
||||
// 检查字段映射
|
||||
if (!empty($this->options['mapping'])) {
|
||||
foreach ($this->options['mapping'] as $name => $alias) {
|
||||
if (isset($result[$name])) {
|
||||
$result[$alias] = $result[$name];
|
||||
unset($result[$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,17 +165,19 @@ trait ResultOperation
|
||||
|
||||
/**
|
||||
* 处理空数据.
|
||||
*
|
||||
* @param Closure $closure 闭包数据
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DataNotFoundException
|
||||
*
|
||||
* @return array|Model|null|static
|
||||
*/
|
||||
protected function resultToEmpty()
|
||||
protected function resultToEmpty(?Closure $closure = null)
|
||||
{
|
||||
if (!empty($this->options['fail'])) {
|
||||
$this->throwNotFound();
|
||||
} elseif ($closure instanceof Closure) {
|
||||
return $closure($this);
|
||||
} elseif (!empty($this->options['allow_empty'])) {
|
||||
return !empty($this->model) ? $this->model->newInstance() : [];
|
||||
}
|
||||
@ -214,12 +226,12 @@ trait ResultOperation
|
||||
if (!empty($this->model)) {
|
||||
$class = get_class($this->model);
|
||||
|
||||
throw new ModelNotFoundException('model data Not Found:'.$class, $class, $this->options);
|
||||
throw new ModelNotFoundException('model data Not Found:' . $class, $class, $this->options);
|
||||
}
|
||||
|
||||
$table = $this->getTable();
|
||||
|
||||
throw new DataNotFoundException('table data not Found:'.$table, $table, $this->options);
|
||||
throw new DataNotFoundException('table data not Found:' . $table, $table, $this->options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
0
vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php
vendored
Executable file → Normal file
4
vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php
vendored
Executable file → Normal file
4
vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php
vendored
Executable file → Normal file
@ -100,6 +100,10 @@ trait TimeFieldQuery
|
||||
public function whereMonth(string $field, string $month = 'this month', int $step = 1, string $logic = 'AND')
|
||||
{
|
||||
if (in_array($month, ['this month', 'last month'])) {
|
||||
if($month === 'last month') {
|
||||
$month = $this->timeRule['last month'][0];
|
||||
}
|
||||
|
||||
$month = date('Y-m', strtotime($month));
|
||||
}
|
||||
|
||||
|
||||
0
vendor/topthink/think-orm/src/db/concern/Transaction.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/concern/Transaction.php
vendored
Executable file → Normal file
156
vendor/topthink/think-orm/src/db/concern/WhereQuery.php
vendored
Executable file → Normal file
156
vendor/topthink/think-orm/src/db/concern/WhereQuery.php
vendored
Executable file → Normal file
@ -9,7 +9,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db\concern;
|
||||
|
||||
@ -37,18 +37,26 @@ trait WhereQuery
|
||||
} elseif (true === $field || 1 === $field) {
|
||||
$this->options['where']['AND'][] = true;
|
||||
|
||||
return $this;
|
||||
} elseif (empty($field)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$pk = $this->getPk();
|
||||
if ((is_null($condition) || '=' == $op) && is_string($pk) && $pk == $field ) {
|
||||
if ((is_null($condition) || '=' == $op) && is_string($pk) && $pk == $field) {
|
||||
$this->options['key'] = is_null($condition) ? $op : $condition;
|
||||
}
|
||||
|
||||
$logic = 'AND';
|
||||
$param = func_get_args();
|
||||
array_shift($param);
|
||||
|
||||
return $this->parseWhereExp('AND', $field, $op, $condition, $param);
|
||||
if (is_array($field) && !empty($field) && array_is_list($field)) {
|
||||
return $this->where(function ($query) use ($param, $condition, $op, $field, $logic) {
|
||||
return $query->parseWhereExp($logic, $field, $op, $condition, $param);
|
||||
});
|
||||
}
|
||||
return $this->parseWhereExp($logic, $field, $op, $condition, $param);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,6 +69,7 @@ trait WhereQuery
|
||||
protected function parseQueryWhere(BaseQuery $query): void
|
||||
{
|
||||
$this->options['where'] = $query->getOptions('where') ?? [];
|
||||
|
||||
$via = $query->getOptions('via');
|
||||
|
||||
if ($via) {
|
||||
@ -87,10 +96,17 @@ trait WhereQuery
|
||||
*/
|
||||
public function whereOr($field, $op = null, $condition = null)
|
||||
{
|
||||
$logic = 'OR';
|
||||
$param = func_get_args();
|
||||
array_shift($param);
|
||||
|
||||
return $this->parseWhereExp('OR', $field, $op, $condition, $param);
|
||||
if (is_array($field) && !empty($field) && array_is_list($field)) {
|
||||
return $this->where(function ($query) use ($param, $condition, $op, $field, $logic) {
|
||||
return $query->parseWhereExp($logic, $field, $op, $condition, $param);
|
||||
});
|
||||
}
|
||||
|
||||
return $this->parseWhereExp($logic, $field, $op, $condition, $param);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -104,10 +120,16 @@ trait WhereQuery
|
||||
*/
|
||||
public function whereXor($field, $op = null, $condition = null)
|
||||
{
|
||||
$logic = 'XOR';
|
||||
$param = func_get_args();
|
||||
array_shift($param);
|
||||
|
||||
return $this->parseWhereExp('XOR', $field, $op, $condition, $param);
|
||||
if (is_array($field) && !empty($field) && array_is_list($field)) {
|
||||
return $this->where(function ($query) use ($param, $condition, $op, $field, $logic) {
|
||||
return $query->parseWhereExp($logic, $field, $op, $condition, $param);
|
||||
});
|
||||
}
|
||||
return $this->parseWhereExp($logic, $field, $op, $condition, $param);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -272,6 +294,33 @@ trait WhereQuery
|
||||
return $this->parseWhereExp($logic, $field, 'FIND IN SET', $condition, [], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定json_contains查询条件.
|
||||
*
|
||||
* @param mixed $field 查询字段
|
||||
* @param mixed $condition 查询条件
|
||||
* @param string $logic 查询逻辑 and or xor
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function whereJsonContains(string $field, $condition, string $logic = 'AND')
|
||||
{
|
||||
if (str_contains($field, '->')) {
|
||||
[$field1, $field2] = explode('->', $field);
|
||||
$field = 'json_extract(' . $field1 . ',\'$.' . $field2 . '\')';
|
||||
}
|
||||
|
||||
$value = is_string($condition) ? '"' . $condition . '"' : $condition;
|
||||
$name = $this->bindValue($value);
|
||||
$bind[$name] = $value;
|
||||
return $this->whereRaw('json_contains(' . $field . ',:' . $name . ')', $bind, $logic);
|
||||
}
|
||||
|
||||
public function whereOrJsonContains(string $field, $condition)
|
||||
{
|
||||
return $this->whereJsonContains($field, $condition, 'OR');
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较两个字段.
|
||||
*
|
||||
@ -282,10 +331,10 @@ trait WhereQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function whereColumn(string $field1, string $operator, string $field2 = null, string $logic = 'AND')
|
||||
public function whereColumn(string $field1, string $operator, ?string $field2 = null, string $logic = 'AND')
|
||||
{
|
||||
if (is_null($field2)) {
|
||||
$field2 = $operator;
|
||||
$field2 = $operator;
|
||||
$operator = '=';
|
||||
}
|
||||
|
||||
@ -309,6 +358,20 @@ trait WhereQuery
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 包含软删除数据.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withTrashed()
|
||||
{
|
||||
if ($this->model) {
|
||||
$this->options['soft_delete'] = null;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定Exp查询条件.
|
||||
*
|
||||
@ -340,7 +403,7 @@ trait WhereQuery
|
||||
{
|
||||
if (is_null($condition)) {
|
||||
$condition = $op;
|
||||
$op = '=';
|
||||
$op = '=';
|
||||
}
|
||||
|
||||
$this->options['where'][$logic][] = [new Raw($field), $op, $condition];
|
||||
@ -389,39 +452,41 @@ trait WhereQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function parseWhereExp(string $logic, $field, $op, $condition, array $param = [], bool $strict = false)
|
||||
protected function parseWhereExp(string $logic, $field, $op, $condition, array $param = [], bool $strict = false): self
|
||||
{
|
||||
$logic = strtoupper($logic);
|
||||
|
||||
// 处理 via
|
||||
if (is_string($field) && !empty($this->options['via']) && !str_contains($field, '.')) {
|
||||
$field = $this->options['via'] . '.' . $field;
|
||||
}
|
||||
|
||||
// 严格模式查询
|
||||
if ($strict) {
|
||||
// 使用严格模式查询
|
||||
if ('=' == $op) {
|
||||
$where = $this->whereEq($field, $condition);
|
||||
} else {
|
||||
$where = [$field, $op, $condition, $logic];
|
||||
}
|
||||
} elseif (is_array($field)) {
|
||||
// 解析数组批量查询
|
||||
return $this->parseStrictWhere($field, $op, $condition, $logic);
|
||||
}
|
||||
|
||||
// 处理批量查询
|
||||
if (is_array($field)) {
|
||||
return $this->parseArrayWhereItems($field, $logic);
|
||||
} elseif ($field instanceof Closure) {
|
||||
}
|
||||
|
||||
// 处理闭包查询
|
||||
if ($field instanceof Closure) {
|
||||
$where = $field;
|
||||
} elseif (is_string($field)) {
|
||||
if ($condition instanceof Raw) {
|
||||
} elseif (preg_match('/[,=\<\'\"\(\s]/', $field)) {
|
||||
return $this->whereRaw($field, is_array($op) ? $op : [], $logic);
|
||||
} elseif (is_string($op) && strtolower($op) == 'exp' && !is_null($condition)) {
|
||||
} elseif (is_string($op) && strtolower($op) === 'exp' && !is_null($condition)) {
|
||||
$bind = isset($param[2]) && is_array($param[2]) ? $param[2] : [];
|
||||
|
||||
return $this->whereExp($field, $condition, $bind, $logic);
|
||||
}
|
||||
|
||||
$where = $this->parseWhereItem($logic, $field, $op, $condition, $param);
|
||||
}
|
||||
|
||||
// 添加条件到查询选项
|
||||
if (!empty($where)) {
|
||||
$this->options['where'][$logic][] = $where;
|
||||
}
|
||||
@ -429,6 +494,19 @@ trait WhereQuery
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function parseStrictWhere($field, $op, $condition, string $logic): self
|
||||
{
|
||||
if ('=' === $op) {
|
||||
$where = $this->whereEq($field, $condition);
|
||||
} else {
|
||||
$where = [$field, $op, $condition, $logic];
|
||||
}
|
||||
|
||||
$this->options['where'][$logic][] = $where;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分析查询表达式.
|
||||
*
|
||||
@ -445,8 +523,10 @@ trait WhereQuery
|
||||
if (is_array($op)) {
|
||||
// 同一字段多条件查询
|
||||
array_unshift($param, $field);
|
||||
$where = $param;
|
||||
} elseif ($field && is_null($condition)) {
|
||||
return $param;
|
||||
}
|
||||
|
||||
if ($field && is_null($condition)) {
|
||||
if (is_string($op) && in_array(strtoupper($op), ['NULL', 'NOTNULL', 'NOT NULL'], true)) {
|
||||
// null查询
|
||||
$where = [$field, $op, ''];
|
||||
@ -458,7 +538,10 @@ trait WhereQuery
|
||||
// 字段相等查询
|
||||
$where = $this->whereEq($field, $op);
|
||||
}
|
||||
} elseif (is_string($op) && in_array(strtoupper($op), ['EXISTS', 'NOT EXISTS', 'NOTEXISTS'], true)) {
|
||||
return $where;
|
||||
}
|
||||
|
||||
if (is_string($op) && in_array(strtoupper($op), ['EXISTS', 'NOT EXISTS', 'NOTEXISTS'], true)) {
|
||||
$where = [$field, $op, is_string($condition) ? new Raw($condition) : $condition];
|
||||
} else {
|
||||
$where = $field ? [$field, $op, $condition, $param[2] ?? null] : [];
|
||||
@ -507,7 +590,7 @@ trait WhereQuery
|
||||
|
||||
if (!empty($where)) {
|
||||
$this->options['where'][$logic] = isset($this->options['where'][$logic]) ?
|
||||
array_merge($this->options['where'][$logic], $where) : $where;
|
||||
array_merge($this->options['where'][$logic], $where) : $where;
|
||||
}
|
||||
|
||||
return $this;
|
||||
@ -545,26 +628,29 @@ trait WhereQuery
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function when($condition, $query, $otherwise = null)
|
||||
public function when($condition, Closure | array $query, Closure | array | null $otherwise = null): self
|
||||
{
|
||||
// 处理条件为 Closure 的情况
|
||||
if ($condition instanceof Closure) {
|
||||
$condition = $condition($this);
|
||||
}
|
||||
|
||||
// 根据条件决定执行哪个查询
|
||||
if ($condition) {
|
||||
if ($query instanceof Closure) {
|
||||
$query($this, $condition);
|
||||
} elseif (is_array($query)) {
|
||||
$this->where($query);
|
||||
}
|
||||
$this->executeQuery($query, $condition);
|
||||
} elseif ($otherwise) {
|
||||
if ($otherwise instanceof Closure) {
|
||||
$otherwise($this, $condition);
|
||||
} elseif (is_array($otherwise)) {
|
||||
$this->where($otherwise);
|
||||
}
|
||||
$this->executeQuery($otherwise, $condition);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function executeQuery(Closure | array $query, $condition): void
|
||||
{
|
||||
if ($query instanceof Closure) {
|
||||
$query($this, $condition);
|
||||
} elseif (is_array($query)) {
|
||||
$this->where($query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
107
vendor/topthink/think-orm/src/db/connector/Mongo.php
vendored
Executable file → Normal file
107
vendor/topthink/think-orm/src/db/connector/Mongo.php
vendored
Executable file → Normal file
@ -7,7 +7,7 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare(strict_types=1);
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think\db\connector;
|
||||
|
||||
@ -42,7 +42,7 @@ use think\db\Mongo as Query;
|
||||
class Mongo extends Connection
|
||||
{
|
||||
// 查询数据类型
|
||||
protected $dbName = '';
|
||||
protected $dbName = '';
|
||||
protected $typeMap = 'array';
|
||||
protected $mongo; // MongoDb Object
|
||||
protected $cursor; // MongoCursor Object
|
||||
@ -94,6 +94,10 @@ class Mongo extends Connection
|
||||
'fields_cache' => false,
|
||||
// 监听SQL
|
||||
'trigger_sql' => true,
|
||||
// Builder类
|
||||
'builder' => '',
|
||||
// Query类
|
||||
'query' => '',
|
||||
// 自动写入时间戳字段
|
||||
'auto_timestamp' => false,
|
||||
// 时间字段取出后的默认时间格式
|
||||
@ -111,7 +115,7 @@ class Mongo extends Connection
|
||||
*/
|
||||
public function getQueryClass(): string
|
||||
{
|
||||
return Query::class;
|
||||
return $this->getConfig('query') ?: Query::class;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,7 +135,7 @@ class Mongo extends Connection
|
||||
*/
|
||||
public function getBuilderClass(): string
|
||||
{
|
||||
return Builder::class;
|
||||
return $this->getConfig('builder') ?: Builder::class;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -154,7 +158,7 @@ class Mongo extends Connection
|
||||
$config = array_merge($this->config, $config);
|
||||
}
|
||||
|
||||
$this->dbName = $config['database'];
|
||||
$this->dbName = $config['database'];
|
||||
$this->typeMap = $config['type_map'];
|
||||
|
||||
if ($config['pk_convert_id'] && '_id' == $config['pk']) {
|
||||
@ -195,7 +199,7 @@ class Mongo extends Connection
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function db(string $db = null)
|
||||
public function db(?string $db = null)
|
||||
{
|
||||
if (is_null($db)) {
|
||||
return $this->dbName;
|
||||
@ -243,8 +247,8 @@ class Mongo extends Connection
|
||||
$this->initConnect($master);
|
||||
$this->db->updateQueryTimes();
|
||||
|
||||
$options = $query->getOptions();
|
||||
$namespace = $options['table'];
|
||||
$options = $query->getOptions();
|
||||
$namespace = $options['table'];
|
||||
|
||||
if (!str_contains($namespace, '.')) {
|
||||
$namespace = $this->dbName . '.' . $namespace;
|
||||
@ -259,7 +263,7 @@ class Mongo extends Connection
|
||||
$mongoQuery = $mongoQuery($query);
|
||||
}
|
||||
|
||||
$readPreference = $options['readPreference'] ?? null;
|
||||
$readPreference = $options['readPreference'] ?? null;
|
||||
$this->queryStartTime = microtime(true);
|
||||
|
||||
if ($session = $this->getSession()) {
|
||||
@ -333,8 +337,8 @@ class Mongo extends Connection
|
||||
|
||||
if ($query->getOptions('cache')) {
|
||||
// 检查查询缓存
|
||||
$cacheItem = $this->parseCache($query, $query->getOptions('cache'));
|
||||
$key = $cacheItem->getKey();
|
||||
$cacheItem = $this->parseCache($query, $query->getOptions('cache'));
|
||||
$key = $cacheItem->getKey();
|
||||
|
||||
if ($this->cache->has($key)) {
|
||||
return $this->cache->get($key);
|
||||
@ -378,8 +382,8 @@ class Mongo extends Connection
|
||||
$this->initConnect(true);
|
||||
$this->db->updateQueryTimes();
|
||||
|
||||
$options = $query->getOptions();
|
||||
$namespace = $options['table'];
|
||||
$options = $query->getOptions();
|
||||
$namespace = $options['table'];
|
||||
if (!str_contains($namespace, '.')) {
|
||||
$namespace = $this->dbName . '.' . $namespace;
|
||||
}
|
||||
@ -389,7 +393,7 @@ class Mongo extends Connection
|
||||
$this->queryStr = 'db' . strstr($namespace, '.') . '.' . $this->queryStr;
|
||||
}
|
||||
|
||||
$writeConcern = $options['writeConcern'] ?? null;
|
||||
$writeConcern = $options['writeConcern'] ?? null;
|
||||
$this->queryStartTime = microtime(true);
|
||||
|
||||
if ($session = $this->getSession()) {
|
||||
@ -410,9 +414,9 @@ class Mongo extends Connection
|
||||
|
||||
if ($query->getOptions('cache')) {
|
||||
// 清理缓存数据
|
||||
$cacheItem = $this->parseCache($query, $query->getOptions('cache'));
|
||||
$key = $cacheItem->getKey();
|
||||
$tag = $cacheItem->getTag();
|
||||
$cacheItem = $this->parseCache($query, $query->getOptions('cache'));
|
||||
$key = $cacheItem->getKey();
|
||||
$tag = $cacheItem->getTag();
|
||||
|
||||
if (isset($key) && $this->cache->has($key)) {
|
||||
$this->cache->delete($key);
|
||||
@ -440,7 +444,7 @@ class Mongo extends Connection
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function command(Command $command, string $dbName = '', ReadPreference $readPreference = null, $typeMap = null, bool $master = false): array
|
||||
public function command(Command $command, string $dbName = '', ?ReadPreference $readPreference = null, $typeMap = null, bool $master = false): array
|
||||
{
|
||||
$this->initConnect($master);
|
||||
$this->db->updateQueryTimes();
|
||||
@ -590,11 +594,11 @@ class Mongo extends Connection
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
$this->mongo = null;
|
||||
$this->cursor = null;
|
||||
$this->linkRead = null;
|
||||
$this->linkWrite = null;
|
||||
$this->links = [];
|
||||
$this->mongo = null;
|
||||
$this->cursor = null;
|
||||
$this->linkRead = null;
|
||||
$this->linkWrite = null;
|
||||
$this->links = [];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -647,7 +651,8 @@ class Mongo extends Connection
|
||||
|
||||
if ($this->config['rw_separate']) {
|
||||
// 主从式采用读写分离
|
||||
if ($master) { // 主服务器写入
|
||||
if ($master) {
|
||||
// 主服务器写入
|
||||
if ($this->config['is_replica_set']) {
|
||||
return $this->replicaSetConnect();
|
||||
} else {
|
||||
@ -681,9 +686,9 @@ class Mongo extends Connection
|
||||
*/
|
||||
public function replicaSetConnect(): Manager
|
||||
{
|
||||
$this->dbName = $this->config['database'];
|
||||
$this->typeMap = $this->config['type_map'];
|
||||
$startTime = microtime(true);
|
||||
$this->dbName = $this->config['database'];
|
||||
$this->typeMap = $this->config['type_map'];
|
||||
$startTime = microtime(true);
|
||||
|
||||
$this->config['params']['replicaSet'] = $this->config['database'];
|
||||
|
||||
@ -740,17 +745,17 @@ class Mongo extends Connection
|
||||
}
|
||||
|
||||
// 生成bulk对象
|
||||
$bulk = $this->builder->insert($query);
|
||||
$writeResult = $this->mongoExecute($query, $bulk);
|
||||
$result = $writeResult->getInsertedCount();
|
||||
$bulk = $this->builder->insert($query);
|
||||
$writeResult = $this->mongoExecute($query, $bulk);
|
||||
$result = $writeResult->getInsertedCount();
|
||||
|
||||
if ($result) {
|
||||
$data = $options['data'];
|
||||
$lastInsId = $this->getLastInsID($query);
|
||||
$data = $options['data'];
|
||||
$lastInsId = $this->getLastInsID($query);
|
||||
|
||||
if ($lastInsId) {
|
||||
$pk = $query->getPk();
|
||||
$data[$pk] = $lastInsId;
|
||||
$pk = $query->getPk();
|
||||
$data[$pk] = $lastInsId;
|
||||
}
|
||||
|
||||
$query->setOption('data', $data);
|
||||
@ -773,7 +778,7 @@ class Mongo extends Connection
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLastInsID(BaseQuery $query, string $sequence = null)
|
||||
public function getLastInsID(BaseQuery $query, ?string $sequence = null)
|
||||
{
|
||||
$id = $this->builder->getLastInsID();
|
||||
|
||||
@ -814,8 +819,8 @@ class Mongo extends Connection
|
||||
}
|
||||
|
||||
// 生成bulkWrite对象
|
||||
$bulk = $this->builder->insertAll($query, $dataSet);
|
||||
$writeResult = $this->mongoExecute($query, $bulk);
|
||||
$bulk = $this->builder->insertAll($query, $dataSet);
|
||||
$writeResult = $this->mongoExecute($query, $bulk);
|
||||
|
||||
return $writeResult->getInsertedCount();
|
||||
}
|
||||
@ -839,9 +844,9 @@ class Mongo extends Connection
|
||||
$query->parseOptions();
|
||||
|
||||
// 生成bulkWrite对象
|
||||
$bulk = $this->builder->update($query);
|
||||
$writeResult = $this->mongoExecute($query, $bulk);
|
||||
$result = $writeResult->getModifiedCount();
|
||||
$bulk = $this->builder->update($query);
|
||||
$writeResult = $this->mongoExecute($query, $bulk);
|
||||
$result = $writeResult->getModifiedCount();
|
||||
|
||||
if ($result) {
|
||||
$this->db->trigger('after_update', $query);
|
||||
@ -870,10 +875,10 @@ class Mongo extends Connection
|
||||
$query->parseOptions();
|
||||
|
||||
// 生成bulkWrite对象
|
||||
$bulk = $this->builder->delete($query);
|
||||
$bulk = $this->builder->delete($query);
|
||||
// 执行操作
|
||||
$writeResult = $this->mongoExecute($query, $bulk);
|
||||
$result = $writeResult->getDeletedCount();
|
||||
$writeResult = $this->mongoExecute($query, $bulk);
|
||||
$result = $writeResult->getDeletedCount();
|
||||
|
||||
if ($result) {
|
||||
$this->db->trigger('after_delete', $query);
|
||||
@ -960,7 +965,7 @@ class Mongo extends Connection
|
||||
|
||||
if (!empty($options['cache'])) {
|
||||
$cacheItem = $this->parseCache($query, $options['cache']);
|
||||
$key = $cacheItem->getKey();
|
||||
$key = $cacheItem->getKey();
|
||||
|
||||
if ($this->cache->has($key)) {
|
||||
return $this->cache->get($key);
|
||||
@ -1003,7 +1008,7 @@ class Mongo extends Connection
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function column(BaseQuery $query, string|array $field, string $key = ''): array
|
||||
public function column(BaseQuery $query, string | array $field, string $key = ''): array
|
||||
{
|
||||
$options = $query->parseOptions();
|
||||
|
||||
@ -1024,8 +1029,8 @@ class Mongo extends Connection
|
||||
|
||||
if (!empty($options['cache'])) {
|
||||
// 判断查询缓存
|
||||
$cacheItem = $this->parseCache($query, $options['cache']);
|
||||
$key = $cacheItem->getKey();
|
||||
$cacheItem = $this->parseCache($query, $options['cache']);
|
||||
$key = $cacheItem->getKey();
|
||||
|
||||
if ($this->cache->has($key)) {
|
||||
return $this->cache->get($key);
|
||||
@ -1120,7 +1125,7 @@ class Mongo extends Connection
|
||||
$this->commit();
|
||||
|
||||
return $result;
|
||||
} catch (\Throwable $e) {
|
||||
} catch (\Throwable $e) {
|
||||
$this->rollback();
|
||||
|
||||
throw $e;
|
||||
@ -1138,7 +1143,7 @@ class Mongo extends Connection
|
||||
public function startTrans()
|
||||
{
|
||||
$this->initConnect(true);
|
||||
$this->session_uuid = uniqid();
|
||||
$this->session_uuid = uniqid();
|
||||
$this->sessions[$this->session_uuid] = $this->getMongo()->startSession();
|
||||
|
||||
$this->sessions[$this->session_uuid]->startTransaction([]);
|
||||
@ -1203,7 +1208,7 @@ class Mongo extends Connection
|
||||
public function getSession()
|
||||
{
|
||||
return ($this->session_uuid && isset($this->sessions[$this->session_uuid]))
|
||||
? $this->sessions[$this->session_uuid]
|
||||
: null;
|
||||
? $this->sessions[$this->session_uuid]
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
0
vendor/topthink/think-orm/src/db/connector/Mysql.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/connector/Mysql.php
vendored
Executable file → Normal file
2
vendor/topthink/think-orm/src/db/connector/Oracle.php
vendored
Executable file → Normal file
2
vendor/topthink/think-orm/src/db/connector/Oracle.php
vendored
Executable file → Normal file
@ -107,7 +107,7 @@ class Oracle extends PDOConnection
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLastInsID(BaseQuery $query, string $sequence = null)
|
||||
public function getLastInsID(BaseQuery $query, ?string $sequence = null)
|
||||
{
|
||||
if (!is_null($sequence)) {
|
||||
$pdo = $this->linkID->query("select {$sequence}.currval as id from dual");
|
||||
|
||||
0
vendor/topthink/think-orm/src/db/connector/Pgsql.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/connector/Pgsql.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/connector/Sqlite.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/connector/Sqlite.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/connector/Sqlsrv.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/connector/Sqlsrv.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/connector/pgsql.sql
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/connector/pgsql.sql
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/connector/pgsql12.sql
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/connector/pgsql12.sql
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/BindParamException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/BindParamException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/DataNotFoundException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/DataNotFoundException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/DbEventException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/DbEventException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/DbException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/DbException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/InvalidArgumentException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/InvalidArgumentException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/ModelEventException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/ModelEventException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/ModelNotFoundException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/ModelNotFoundException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/PDOException.php
vendored
Executable file → Normal file
0
vendor/topthink/think-orm/src/db/exception/PDOException.php
vendored
Executable file → Normal file
Reference in New Issue
Block a user