Files
2026-08-31 11:33:59 +08:00

1121 lines
32 KiB
PHP

<?php
/**
*+------------------
* madong
*+------------------
* Copyright (c) https://gitee.com/motion-code All rights reserved.
*+------------------
* Author: Mr. April (405784684@qq.com)
*+------------------
* Official Website: http://www.madong.tech
*/
namespace core\base;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Pagination\LengthAwarePaginator;
use madong\helper\Arr;
use ReflectionException;
use support\Db;
use Throwable;
use madong\query\traits\WithQueryParams;
/**
* @method count(array $where = [], bool $search = true)
* @method selectList(array $where, array|string $field = '*', int $page = 0, int $limit = 0, string $order = '', array $with = [], bool $search = false)
* @method selectModel(array $where, string $field = '*', int $page = 0, int $limit = 0, string $order = '', array $with = [], bool $search = false)
* @method getCount(array $where)
* @method getDistinctCount(array $where, $field, bool $search = true)
* @method getPk()
* @method getTableName()
* @method get($id, ?array $field = null, ?array $with = [], string $order = '', ?array $withoutScopes = null): ?Model
* @method be($map, string $field = '')
* @method getOne(array $where, ?string $field = '*', array $with = [])
* @method value($where, ?string $field = '')
* @method getColumn(array $where, string $field, string $key = '')
* @method delete(array|int|string $id, ?string $key = null)
* @method destroy(mixed $id, bool $force = false)
* @method update(string|int|array $id, array $data, ?string $key = null)
* @method setWhere($where, ?string $key = null)
* @method batchUpdate(array $ids, array $data, ?string $key = null)
* @method save(array $data)
* @method saveAll(array $data)
* @method getFieldValue($value, string $filed, ?string $valueKey = '', ?array $where = [])
* @method search(array $where = [], bool $search = true)
* @method sum(array $where, string $field, bool $search = false)
* @method bcInc($key, string $incField, string $inc, string $keyField = null, int $acc = 2)
* @method bcDec($key, string $decField, string $dec, string $keyField = null, int $acc = 2)
* @method getMax(array $where = [], string $field = '')
* @method getMin(array $where = [], string $field = '')
* @method decStockIncSales(array $where, int $num, string $stock = 'stock', string $sales = 'sales')
* @method incStockDecSales(array $where, int $num, string $stock = 'stock', string $sales = 'sales')
*/
/**
* 基础Dao
*
* @author Mr.April
* @since 1.0
*/
abstract class BaseDao
{
use WithQueryParams;
/**
* 获取当前模型
*
* @return string
*/
abstract protected function setModel(): string;
/**
* 获取条数
*
* @param array $where
* @param bool $search
*
* @return int
* @throws Exception
*/
public function count(array $where = [], bool $search = false): int
{
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$query = $this->applyQueryParams($query, $where, $this->getQueryOptions($search));
}
return $query->count();
}
/**
* 查询列表
*
* @param array $where
* @param string|array $field
* @param int $page
* @param int $limit
* @param string $order
* @param array $with
* @param bool $search
* @param array|null $withoutScopes
*
* @return Collection|null
* @throws \Exception
*/
public function selectList(array $where, string|array $field = '*', int $page = 0, int $limit = 0, string $order = '', array $with = [], bool $search = false, ?array $withoutScopes = null): ?Collection
{
// 使用 selectModel 方法获取查询构建器
$query = $this->selectModel($where, $field, $page, $limit, $order, $with, $search, $withoutScopes);
// 如果字段不是 '*' 或 ['*'],则应用 selectRaw()
$isWildcard = ($field === '*' || ($field === ['*']));
if (!$isWildcard) {
if (is_array($field)) {
// 如果是数组,转换为字符串
$field = implode(',', $field);
}
$query->selectRaw($field);
}
// 应用分页
if ($page > 0 && $limit > 0) {
// 只返回数据部分
return $query->paginate($limit, ['*'], 'page', $page)->getCollection();
}
return $query->get(); // 返回所有数据
}
/**
* 获取某些条件数据
*
* @param array $where
* @param array|string $field
* @param int $page
* @param int $limit
* @param string $order
* @param array $with
* @param bool $search
* @param array|null $withoutScopes
*
* @return Builder|\Illuminate\Database\Query\Builder|LengthAwarePaginator|null
* @throws Exception
*/
public function selectModel(array $where, array|string $field = '*', int $page = 0, int $limit = 0, string $order = '', array $with = [], bool $search = false, ?array $withoutScopes = null): Builder|\Illuminate\Database\Query\Builder|LengthAwarePaginator|null
{
// 获取模型的查询构建器
$query = $this->getModel()->query();
// 作用域处理
if (!empty($withoutScopes)) {
$this->applyScopeRemoval($query, $withoutScopes);
}
// 使用查询参数模块处理条件
if (!empty($where)) {
$options = [
'keyword_fields' => $this->getKeywordFields(),
];
// $search 为 false 时,禁用搜索器
if (!$search) {
$options['scopes'] = [];
}
$query = $this->applyQueryParams($query, $where, $options);
}
// 应用字段选择
$isWildcard = ($field === '*' || ($field === ['*']));
if (!$isWildcard) {
if (is_array($field)) {
// 过滤空值并合并为字符串
$field = array_filter($field, function ($f) {
return !empty($f);
});
$field = implode(',', $field);
}
if (!empty($field)) {
$query->selectRaw($field);
}
}
// 应用分页和其他查询条件
if ($page > 0 && $limit > 0) {
$query->paginate($limit, ['*'], 'page', $page);
}
if ($order !== '') {
$query->orderByRaw($order);
}
if (!empty($with)) {
$query->with($with);
}
return $query; // 返回查询构建器
}
/**
* 获取条数
*
* @param array $where
*
* @return int
* @throws Exception
*/
public function getCount(array $where): int
{
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$query = $this->applyQueryParams($query, $where, $this->getQueryOptions(true));
}
return $query->count();
}
/**
* 获取条数
*
* @param array $where
* @param string $field
*
* @return int
* @throws Exception
*/
public function getDistinctCount(array $where, string $field): int
{
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$query = $this->applyQueryParams($query, $where, $this->getQueryOptions(true));
}
return $query->distinct()->count($field);
}
/**
* 获取模型
*
* @return mixed
* @throws Exception
*/
public function getModel(): mixed
{
try {
$className = $this->setModel();
if (!class_exists($className)) {
throw new Exception($className . ' 不是一个有效的模型类');
}
return new $className();
} catch (Throwable $e) {
throw new Exception($className . ' 未知模型: ' . $e->getMessage());
}
}
/**
* 获取查询构建器
*
* @return \Illuminate\Database\Eloquent\Builder
* @throws Exception
*/
public function query(): \Illuminate\Database\Eloquent\Builder
{
return $this->getModel()->query();
}
/**
* 根据ID查找记录
*
* @param int $id
* @return \Illuminate\Database\Eloquent\Model|null
* @throws Exception
*/
public function find(int $id): ?\Illuminate\Database\Eloquent\Model
{
return $this->query()->find($id);
}
/**
* 添加查询条件
*
* @param mixed $column
* @param mixed $operator
* @param mixed $value
* @return \Illuminate\Database\Eloquent\Builder
* @throws Exception
*/
public function where($column, $operator = null, $value = null): \Illuminate\Database\Eloquent\Builder
{
return $this->query()->where($column, $operator, $value);
}
/**
* 获取模型主键
*
* @return string
* @throws Exception
*/
public function getPk(): string
{
return $this->getModel()->getKeyName();
}
/**
* 获取表名
*
* @return string
* @throws ReflectionException|Exception
*/
public function getTableName(): string
{
return $this->getModel()->getTable();
}
/**
* 获取一条数据
*
* @param $id
* @param array|null $field
* @param array|null $with
* @param string $order
* @param array|null $withoutScopes
*
* @return Model|null
* @throws \Exception
*/
public function get($id, ?array $field = null, ?array $with = [], string $order = '', ?array $withoutScopes = null): ?Model
{
$where = is_array($id) ? $id : [$this->getPk() => $id];
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$query = $this->applyQueryParams($query, $where, $this->getQueryOptions(true));
}
$this->applyScopeRemoval($query, $withoutScopes);
// 添加关联加载
if (!empty($with)) {
$query->with($with);
}
// 添加排序条件
if ($order !== '') {
$query->orderByRaw($order);
}
return $query->select($field ?? ['*'])->first();
}
/**
* 查询一条数据是否存在
*
* @param $map
* @param string $field
*
* @return bool
* @throws Exception
*/
public function be($map, string $field = ''): bool
{
// 如果 $map 不是数组且 $field 为空,使用主键
if (!is_array($map) && empty($field)) {
$field = $this->getPk();
}
// 如果 $map 不是数组,将其转换为数组
$map = !is_array($map) ? [$field => $map] : $map;
// 使用 Eloquent 查询构建器检查记录是否存在
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($map)) {
$query = $this->applyQueryParams($query, $map, $this->getQueryOptions(true));
}
return $query->exists();
}
/**
* 根据条件获取一条数据
*
* @param array $where
* @param string|null $field
* @param array $with
*
* @return Model|null
* @throws Exception
*/
public function getOne(array $where, ?string $field = '*', array $with = []): ?Model
{
// 将字段字符串转换为数组
$fieldArray = $field === '*' ? ['*'] : explode(',', $field);
// 使用 Eloquent 查询构建器获取一条数据
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$query = $this->applyQueryParams($query, $where, $this->getQueryOptions(true));
}
// 添加关联加载
if (!empty($with)) {
$query->with($with);
}
return $query->select($fieldArray)->first();
}
/**
* 获取某字段的值
*
* @param $where
* @param string|null $field
*
* @return mixed
* @throws Exception
*/
public function value($where, ?string $field = null): mixed
{
$pk = $this->getPk(); // 获取主键
$where = $this->setWhere($where); // 设置查询条件
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$query = $this->applyQueryParams($query, $where, $this->getQueryOptions(true));
}
return $query->value($field ?? $pk); // 返回指定字段的值,默认为主键
}
/**
* 获取某个字段数组
*
* @param array $where
* @param string $field
* @param string $key
*
* @return array
* @throws ReflectionException|Exception
*/
public function getColumn(array $where, string $field, string $key = ''): array
{
// 使用 Eloquent 查询构建器获取字段数组
$query = $this->getModel()->query();
// 使用查询参数模块处理条件(禁用排序,避免 Pivot 表没有 id 字段的问题)
if (!empty($where)) {
$options = $this->getQueryOptions(true);
$options['apply_sort'] = false; // 禁用排序
$query = $this->applyQueryParams($query, $where, $options);
}
// 如果指定了键,则使用 keyBy 方法
if ($key) {
return $query->pluck($field, $key)->toArray();
}
// 否则,直接获取字段数组
return $query->pluck($field)->toArray();
}
/**
* 删除
*
* @param array|int|string $id
* @param string|null $key
*
* @return mixed
* @throws Exception
*/
public function delete(array|int|string $id, ?string $key = null): int
{
try {
$query = $this->getModel()->query();
if (is_array($id)) {
if (array_is_list($id)) {
//主键列表批量删除
return $this->getModel()->destroy($id);
} else {
foreach ($id as $field => $value) {
$query->where($field, $value);
}
}
} else {
$query->where($key ?: $this->getPk(), $id);
}
$models = $query->get();
if ($models->isEmpty()) {
return 0;
}
foreach ($models as $model) {
$model->delete();//触发事件
}
return $models->count();
} catch (Exception $e) {
$code = (int)$e->getCode();
throw new Exception("删除失败:" . $e->getMessage(), $code);
}
}
/**
* 删除记录
*
* @param mixed $id
* @param bool $force
*
* @return bool
* @throws Exception
*/
public function destroy(mixed $id, bool $force = false): bool
{
// 使用 Eloquent 的 destroy 方法删除记录
return $this->getModel()->destroy($id, $force) > 0;
}
/**
* 更新
*
* @param string|int|array $id
* @param array $data
* @param string|null $key
*
* @return mixed
* @throws Exception
*/
public function update(string|int|array $id, array $data, ?string $key = null): mixed
{
$where = is_array($id) ? $id : [is_null($key) ? $this->getPk() : $key => $id];
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$query = $this->applyQueryParams($query, $where, []);
}
return $query->update($data);
}
/**
* setWhere
*
* @param $where
* @param string|null $key
*
* @return array
* @throws Exception
*/
protected function setWhere($where, ?string $key = null): array
{
// 如果 $where 不是数组,则构建数组
if (!is_array($where)) {
$where = [is_null($key) ? $this->getPk() : $key => $where];
}
return $where;
}
/**
* 批量更新
*
* @param array $ids
* @param array $data
* @param string|null $key
*
* @return mixed
* @throws Exception
*/
public function batchUpdate(array $ids, array $data, ?string $key = null): bool
{
return $this->getModel()->whereIn(is_null($key) ? $this->getPk() : $key, $ids)->update($data);
}
/**
* 保存返回模型
*
* @param array $data
*
* @return Model|null
* @throws Exception
*/
public function save(array $data): ?Model
{
return $this->getModel()->create($data);
}
/**
* 批量插入
*
* @param array $data
*
* @return bool
*/
public function saveAll(array $data): bool
{
if (empty($data)) {
return false;
}
try {
// 对于 Pivot 表或没有复杂逻辑的表,使用批量插入更高效
if ($this->getModel() instanceof \Illuminate\Database\Eloquent\Relations\Pivot ||
(method_exists($this->getModel(), 'usesTimestamps') && !$this->getModel()->usesTimestamps())) {
// 检查是否已存在(避免重复插入)
$existing = $this->getExistingRecords($data);
$newData = $this->filterExistingRecords($data, $existing);
if (empty($newData)) {
// 所有记录都已存在
return true;
}
// 使用批量插入
$result = $this->getModel()->insert($newData);
if (!$result) {
throw new \Exception("批量插入失败,受影响的行数为 0");
}
return $result;
}
// 对于有复杂逻辑(如事件、观察者)的模型,使用逐个保存
$models = $this->getModel()->newCollection();
foreach ($data as $item) {
$models->push($this->getModel()->newInstance($item));
}
$savedAll = true;
$errors = [];
$models->each(function ($model) use (&$savedAll, &$errors) {
if (!$model->save()) {
$savedAll = false;
// 收集验证错误
if (method_exists($model, 'getErrors')) {
$errors[] = $model->getErrors();
}
}
});
if (!$savedAll && !empty($errors)) {
throw new \Exception("批量保存失败: " . json_encode($errors));
}
return $savedAll;
} catch (Exception $e) {
// 重新抛出异常,让调用者知道具体错误
throw new \Exception("批量保存数据失败: " . $e->getMessage(), 0, $e);
}
}
/**
* 获取已存在的记录(用于避免重复插入)
*
* @param array $data
* @return array
*/
protected function getExistingRecords(array $data): array
{
if (empty($data)) {
return [];
}
// 假设数据有 member_id 和 tag_id 这样的复合唯一键
// 可以根据实际情况重写此方法
$query = $this->getModel()->query();
foreach ($data as $item) {
$query->orWhere(function($q) use ($item) {
foreach ($item as $field => $value) {
$q->where($field, $value);
}
});
}
return $query->get()->toArray();
}
/**
* 过滤掉已存在的记录
*
* @param array $data
* @param array $existing
* @return array
*/
protected function filterExistingRecords(array $data, array $existing): array
{
if (empty($existing)) {
return $data;
}
$existingMap = [];
foreach ($existing as $record) {
$key = '';
foreach ($data[0] as $field => $value) {
$key .= $record[$field] ?? '';
}
$existingMap[$key] = true;
}
$newData = [];
foreach ($data as $item) {
$key = '';
foreach ($item as $field => $value) {
$key .= $value;
}
if (!isset($existingMap[$key])) {
$newData[] = $item;
}
}
return $newData;
}
/**
* 获取某字段内的值
*
* @param $value
* @param string $field
* @param string|null $valueKey
* @param array|null $where
*
* @return mixed
* @throws Exception
*/
public function getFieldValue($value, string $field, ?string $valueKey = null, ?array $where = []): mixed
{
// 如果提供了 $valueKey,则构建查询条件
if ($valueKey) {
$where[$valueKey] = $value; // 将 valueKey 和 value 加入条件
} else {
$where[$this->getPk()] = $value; // 默认使用主键作为条件
}
// 使用 Eloquent 查询构建器获取字段值
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$query = $this->applyQueryParams($query, $where, $this->getQueryOptions(true));
}
return $query->value($field);
}
/**
* 根据搜索器获取内容
*
* @param array $where
*
* @return \Illuminate\Database\Query\Builder
* @throws Exception
*/
protected function withSearchSelect(array $where): mixed
{
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
$query = $this->applyQueryParams($query, $where, $this->getQueryOptions(true));
return $query;
}
/**
* 获取关键词搜索字段(子类可重写)
*
* @return array
*/
protected function getKeywordFields(): array
{
return [];
}
/**
* 获取使用搜索器的字段列表(子类可重写)
* 返回空数组表示自动检测所有字段
*
* @return array
*/
protected function getScopeFields(): array
{
return [];
}
/**
* 获取查询参数配置选项
*
* @param bool $search 是否启用搜索器
* @return array
*/
protected function getQueryOptions(bool $search = false): array
{
$options = [
'keyword_fields' => $this->getKeywordFields(),
];
// $search 为 false 时,禁用搜索器
if (!$search) {
$options['scopes'] = [];
}
return $options;
}
/**
* 过滤数据表中不存在的字段
*
* @param array $where
*
* @return array
* @throws Exception
*/
protected function filterWhere(array $where = []): array
{
$fields = $this->getModel()->getFields(); // 获取模型的可填充字段
foreach ($where as $key => $item) {
// 检查键是否在可填充字段中
if (!in_array($key, $fields)) {
unset($where[$key]); // 过滤掉不存在的字段
}
}
return $where; // 返回过滤后的条件
}
/**
* 搜索
*
* @param array $where
*
* @return mixed
* @throws Exception
*/
public function search(array $where = []): mixed
{
if ($where) {
return $this->withSearchSelect($where); // 返回查询构建器
} else {
return $this->getModel(); // 返回模型实例
}
}
/**
* 求和
*
* @param array $where
* @param string $field
* @param bool $search
*
* @return float
* @throws Exception
*/
public function sum(array $where, string $field, bool $search = false): float
{
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$query = $this->applyQueryParams($query, $where, $this->getQueryOptions($search));
}
return (float)$query->sum($field);
}
/**
* 高精度加法(修正精度问题)
*
* @param mixed $key 主键值或条件值
* @param string $incField 要增加的字段
* @param string $inc 增加的值
* @param string|null $keyField 条件字段名,默认为'id'
* @param int $acc 精度(小数位数)
*
* @return bool
* @throws Exception
*/
public function bcInc(mixed $key, string $incField, string $inc, string $keyField = null, int $acc = 2): bool
{
// 获取模型实例
$model = $this->getModel();
// 构建查询条件
$query = $keyField ? $model->where($keyField, $key) : $model->where('id', $key);
// 执行增量操作,使用合适的精度 DECIMAL(10, $acc)
return $query->update([$incField => Db::raw("COALESCE($incField, 0) + CAST($inc AS DECIMAL(10, $acc))")]) > 0;
}
/**
* 高精度 减法
*
* @param $key
* @param string $decField
* @param string $dec
* @param string|null $keyField
* @param int $acc
*
* @return bool
* @throws ReflectionException
*/
public function bcDec($key, string $decField, string $dec, string $keyField = null, int $acc = 2): bool
{
return $this->bc($key, $decField, $dec, $keyField, 2, $acc);
}
/**
* 高精度计算并保存
*
* @param $key
* @param string $field
* @param string $value
* @param string|null $keyField
* @param int $type
* @param int $acc
*
* @return bool
* @throws ReflectionException
*/
public function bc($key, string $field, string $value, string $keyField = null, int $type = 1, int $acc = 2): bool
{
// 获取记录
$result = $keyField === null ? $this->get($key) : $this->getOne([$keyField => $key]);
if (!$result) return false;
$newValue = 0;
if ($type === 1) {
// 加法
$newValue = bcadd($result->{$field}, $value, $acc);
} elseif ($type === 2) {
// 减法
if ($result->{$field} < $value) return false; // 检查是否足够减去
$newValue = bcsub($result->{$field}, $value, $acc);
}
// 更新字段
$result->{$field} = $newValue;
// 保存更新
return $result->save();
}
/**
* 减库存加销量
*
* @param array $where
* @param int $num
* @param string $stock
* @param string $sales
*
* @return bool
* @throws Exception
*/
public function decStockIncSales(array $where, int $num, string $stock = 'stock', string $sales = 'sales'): bool
{
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$query = $this->applyQueryParams($query, $where, $this->getQueryOptions(true));
}
$product = $query->first();
if ($product) {
// 重新构建查询以执行更新操作
$updateQuery = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$updateQuery = $this->applyQueryParams($updateQuery, $where, $this->getQueryOptions(true));
}
return $updateQuery->decrement($stock, $num)->increment($sales, $num);
}
return false;
}
/**
* 加库存减销量
*
* @param array $where
* @param int $num
* @param string $stock
* @param string $sales
*
* @return bool
* @throws Exception
*/
public function incStockDecSales(array $where, int $num, string $stock = 'stock', string $sales = 'sales'): bool
{
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$query = $this->applyQueryParams($query, $where, $this->getQueryOptions(true));
}
$product = $query->first();
if ($product) {
// 重新构建查询以执行更新操作
$updateQuery1 = $this->getModel()->query();
$updateQuery2 = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$updateQuery1 = $this->applyQueryParams($updateQuery1, $where, $this->getQueryOptions(true));
$updateQuery2 = $this->applyQueryParams($updateQuery2, $where, $this->getQueryOptions(true));
}
$updateQuery1->increment($stock, $num);
$updateQuery2->decrement($sales, $num);
return true;
}
return false;
}
/**
* 获取条件数据中的某个值的最大值
*
* @param array $where
* @param string $field
*
* @return mixed
* @throws Exception
*/
public function getMax(array $where = [], string $field = ''): mixed
{
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$query = $this->applyQueryParams($query, $where, $this->getQueryOptions(true));
}
return $query->max($field);
}
/**
* 获取条件数据中的某个值的最小值
*
* @param array $where
* @param string $field
*
* @return mixed
* @throws Exception
*/
public function getMin(array $where = [], string $field = ''): mixed
{
$query = $this->getModel()->query();
// 使用查询参数模块处理条件
if (!empty($where)) {
$query = $this->applyQueryParams($query, $where, $this->getQueryOptions(true));
}
return $query->min($field);
}
private function studly(string $string): string
{
// 用下划线分隔单词
$words = preg_split('/[\s_]+/', $string);
// 将每个单词的首字母大写并连接
$studlyCase = array_map('ucfirst', $words);
// 返回连接后的结果
return implode('', $studlyCase);
}
/**
* 执行作用域移除操作
*
* @param $query
* @param array|null $scopes
*/
protected function applyScopeRemoval($query, ?array $scopes): void
{
if (empty($scopes)) return;
foreach ($scopes as $scope) {
// 全局作用域移除
if (is_string($scope) && class_exists($scope)) {
$query->withoutGlobalScope($scope);
} // 本地作用域移除
elseif (is_string($scope)) {
$query->withoutNamedScope($scope);
} // 闭包动态移除
elseif ($scope instanceof \Closure) {
$scope($query);
}
}
}
/**
* 是否in条件
*
* @param array $condition
*
* @return bool
*/
protected function isInCondition(array $condition): bool
{
return count($condition) === 3
&& in_array(strtolower($condition[1] ?? ''), ['in', 'not in'], true);
}
/**
* 检测表是否存在
*
* @param $table
*
* @return bool
*/
public function tableExists($table): bool
{
return Db::schema()->hasTable($table);
}
}