* @Link https://gitee.com/xmo/MineAdmin */ namespace Builder\Traits; use Hyperf\Contract\LengthAwarePaginatorInterface; use Hyperf\Database\Model\Builder; use Hyperf\Database\Model\Model; use Builder\Annotation\Transaction; use Builder\BaseCollection; use Builder\BaseModel; trait MapperTrait { /** * @var BaseModel */ public $model; /** * 获取列表数据 * @param array|null $params * @param bool $isScope * @return array */ public function getList(?array $params, bool $isScope = true): array { return $this->listQuerySetting($params, $isScope)->get()->toArray(); } /** * 获取列表数据(带分页) * @param array|null $params * @param bool $isScope * @param string $pageName * @return array */ public function getPageList(?array $params, bool $isScope = true, string $pageName = 'page'): array { $paginate = $this->listQuerySetting($params, $isScope)->paginate( $params['pageSize'] ?? $this->model::PAGE_SIZE, ['*'], $pageName, $params[$pageName] ?? 1 ); return $this->setPaginate($paginate); } /** * 设置数据库分页 * @param LengthAwarePaginatorInterface $paginate * @return array */ public function setPaginate(LengthAwarePaginatorInterface $paginate): array { return [ 'items' => $paginate->items(), 'pageInfo' => [ 'total' => $paginate->total(), 'currentPage' => $paginate->currentPage(), 'totalPage' => $paginate->lastPage() ] ]; } /** * 获取树列表 * @param array|null $params * @param bool $isScope * @param string $id * @param string $parentField * @param string $children * @return array */ public function getTreeList( ?array $params = null, bool $isScope = true, string $id = 'id', string $parentField = 'parent_id', string $children='children' ): array { $params['_mineadmin_tree'] = true; $params['_mineadmin_tree_pid'] = $parentField; $data = $this->listQuerySetting($params, $isScope)->get(); return $data->toTree([], $data[0]->{$parentField} ?? 0, $id, $parentField, $children); } /** * 返回模型查询构造器 * @param array|null $params * @param bool $isScope * @return Builder */ public function listQuerySetting(?array $params, bool $isScope): Builder { $query = (($params['recycle'] ?? false) === true) ? $this->model::onlyTrashed() : $this->model::query(); if ($params['select'] ?? false) { $query->select($this->filterQueryAttributes($params['select'])); } $query = $this->handleOrder($query, $params); $isScope && $query->userDataScope(); return $this->handleSearch($query, $params); } /** * 排序处理器 * @param Builder $query * @param array|null $params * @return Builder */ public function handleOrder(Builder $query, ?array &$params = null): Builder { // 对树型数据强行加个排序 if (isset($params['_mineadmin_tree'])) { $query->orderBy($params['_mineadmin_tree_pid']); } if ($params['orderBy'] ?? false) { if (is_array($params['orderBy'])) { foreach ($params['orderBy'] as $key => $order) { $query->orderBy($order, $params['orderType'][$key] ?? 'asc'); } } else { $query->orderBy($params['orderBy'], $params['orderType'] ?? 'asc'); } } return $query; } /** * 搜索处理器 * @param Builder $query * @param array $params * @return Builder */ public function handleSearch(Builder $query, array $params): Builder { return $query; } /** * 过滤查询字段不存在的属性 * @param array $fields * @param bool $removePk * @return array */ protected function filterQueryAttributes(array $fields, bool $removePk = false): array { $model = new $this->model; $attrs = $model->getFillable(); foreach ($fields as $key => $field) { if (!in_array(trim($field), $attrs) && mb_strpos(str_replace('AS', 'as', $field), 'as') === false) { unset($fields[$key]); } else { $fields[$key] = trim($field); } } if ($removePk && in_array($model->getKeyName(), $fields)) { unset($fields[array_search($model->getKeyName(), $fields)]); } $model = null; return ( count($fields) < 1 ) ? ['*'] : $fields; } /** * 过滤新增或写入不存在的字段 * @param array $data * @param bool $removePk */ protected function filterExecuteAttributes(array &$data, bool $removePk = false): void { $model = new $this->model; $attrs = $model->getFillable(); foreach ($data as $name => $val) { if (!in_array($name, $attrs)) { unset($data[$name]); } } if ($removePk && isset($data[$model->getKeyName()])) { unset($data[$model->getKeyName()]); } $model = null; } /** * 新增数据 * @param array $data * @return int */ public function save(array $data): int { $this->filterExecuteAttributes($data, $this->getModel()->incrementing); $model = $this->model::create($data); return $model->{$model->getKeyName()}; } /** * 读取一条数据 * @param int $id * @return BaseModel|null */ public function read(int $id): ?BaseModel { return ($model = $this->model::find($id)) ? $model : null; } /** * 按条件读取一行数据 * @param array $condition * @param array $column * @return mixed */ public function first(array $condition, array $column = ['*']): ?BaseModel { return ($model = $this->model::where($condition)->first($column)) ? $model : null; } /** * 获取单个值 * @param array $condition * @param string $columns * @return \Hyperf\Utils\HigherOrderTapProxy|mixed|void|null */ public function value(array $condition, string $columns = 'id') { return ($model = $this->model::where($condition)->value($columns)) ? $model : null; } /** * 获取单列值 * @param array $condition * @param string $columns * @return array */ public function pluck(array $condition, string $columns = 'id'): array { return $this->model::where($condition)->pluck($columns)->toArray(); } /** * 从回收站读取一条数据 * @param int $id * @return BaseModel|null * @noinspection PhpUnused */ public function readByRecycle(int $id): ?BaseModel { return ($model = $this->model::withTrashed()->find($id)) ? $model : null; } /** * 单个或批量软删除数据 * @param array $ids * @return bool */ public function delete(array $ids): bool { $this->model::destroy($ids); return true; } /** * 更新一条数据 * @param int $id * @param array $data * @return bool */ public function update(int $id, array $data): bool { $this->filterExecuteAttributes($data, true); return $this->model::find($id)->update($data) > 0; } /** * 按条件更新数据 * @param array $condition * @param array $data * @return bool */ public function updateByCondition(array $condition, array $data): bool { $this->filterExecuteAttributes($data, true); return $this->model::query()->where($condition)->update($data) > 0; } /** * 单个或批量真实删除数据 * @param array $ids * @return bool */ public function realDelete(array $ids): bool { foreach ($ids as $id) { $model = $this->model::withTrashed()->find($id); $model && $model->forceDelete(); } return true; } /** * 单个或批量从回收站恢复数据 * @param array $ids * @return bool */ public function recovery(array $ids): bool { $this->model::withTrashed()->whereIn((new $this->model)->getKeyName(), $ids)->restore(); return true; } /** * 单个或批量禁用数据 * @param array $ids * @param string $field * @return bool */ public function disable(array $ids, string $field = 'status'): bool { $this->model::query()->whereIn((new $this->model)->getKeyName(), $ids)->update([$field => $this->model::DISABLE]); return true; } /** * 单个或批量启用数据 * @param array $ids * @param string $field * @return bool */ public function enable(array $ids, string $field = 'status'): bool { $this->model::query()->whereIn((new $this->model)->getKeyName(), $ids)->update([$field => $this->model::ENABLE]); return true; } /** * @return BaseModel */ public function getModel(): BaseModel { return new $this->model; } /** * 数据导入 * @param string $dto * @param \Closure|null $closure * @return bool * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface */ #[Transaction] public function import(string $dto, ?\Closure $closure = null): bool { return (new BaseCollection())->import($dto, $this->getModel(), $closure); } /** * 闭包通用查询设置 * @param \Closure|null $closure 传入的闭包查询 * @return Builder */ public function settingClosure(?\Closure $closure = null): Builder { return $this->model::where(function($query) use($closure) { if ($closure instanceof \Closure) { $closure($query); } }); } /** * 闭包通用方式查询一条数据 * @param \Closure|null $closure * @param array|string[] $column * @return Builder|Model|null */ public function one(?\Closure $closure = null, array $column = ['*']) { return $this->settingClosure($closure)->select($column)->first(); } /** * 闭包通用方式查询数据集合 * @param \Closure|null $closure * @param array|string[] $column * @return array */ public function get(?\Closure $closure = null, array $column = ['*']): array { return $this->settingClosure($closure)->get($column)->toArray(); } /** * 闭包通用方式统计 * @param \Closure|null $closure * @param string $column * @return int */ public function count(?\Closure $closure = null, string $column = '*'): int { return $this->settingClosure($closure)->count($column); } /** * 闭包通用方式查询最大值 * @param \Closure|null $closure * @param string $column * @return mixed|string|void */ public function max(?\Closure $closure = null, string $column = '*') { return $this->settingClosure($closure)->max($column); } /** * 闭包通用方式查询最小值 * @param \Closure|null $closure * @param string $column * @return mixed|string|void */ public function min(?\Closure $closure = null, string $column = '*') { return $this->settingClosure($closure)->min($column); } /** * 数字更新操作 * @param int $id * @param string $field * @param int $value * @return bool */ public function numberOperation(int $id, string $field, int $value): bool { return $this->update($id, [ $field => $value]); } }