model = $model; } elseif (strpos($class, '\\repository') > 0) { $model = str_replace('\\repository', '\\model', $class); //去掉末尾Repository app\model\AccountRepository =》 app\model\Account $model = substr($model, 0, strlen($model) - strlen('Repository')); if (class_exists($model)) { $obj->model = new $model; } } self::$objects[$class] = $obj; return $obj; } /** * @param callable $callback * @param mixed $failReturn * @param bool $transaction * @return mixed * @throws RepositoryException */ protected function access(callable $callback, $failReturn, bool $transaction = false) { $exception = null; try { if ($transaction) { Db::startTrans(); } $r = $callback(); if ($transaction) { Db::commit(); } if ($r) { return $r; } if ($failReturn instanceof Exception) { return null; } return $failReturn; } catch (Exception $e) { if ($transaction) { Db::rollback(); } if ($e instanceof RepositoryException) { throw $e; } $name = 'Domain - Repository - 未知错误'; $traces = $e->getTrace(); foreach ($traces as $i => $trace) { if (!empty($trace['class']) && $trace['class'] === Repository::class && $trace['function'] === 'access') { $trace = $traces[$i - 2] ?? null; break; } } if (!empty($trace) && !empty($trace['file'][1]) && !empty($trace['line'])) { $parts = explode('application\\', $trace['file']); if (!empty($parts[1])) { $name = $parts[1].':'.$trace['line']; } else { $name = $trace['file'].':'.$trace['line']; } } $exception = $e; $line = '['.$name.'] '.$e->getMessage(); Log::error($line); throw new RepositoryException('Repository异常'.(Env::get('app_debug') ? ': '.$line : ''), 5009); } finally { if ($exception && $failReturn instanceof RepositoryException) { if (Env::get('app_debug')) { $failReturn = new RepositoryException($failReturn->getMessage().': '.$exception->getMessage(), $failReturn->getCode()); } throw $failReturn; } } } /** * 获取当前model对象 * * @return Model */ public function getModel(): Model { return $this->model; } /** * 根据条件查询列表 * * @param array $where 查询条件 * @param array $fields 查询字段 []表示全部 * @param int $page 默认第一页 0不限制 * @param int $limit 限制条数 0不限制 * @param callable|null $callback 更为复杂的条件 使用闭包查询 * @return array * @throws RepositoryException */ public function findList(array $where = [], array $fields = [], int $page = 1, int $limit = 0, callable $callback = null, array $order = []): ?array { $failData = [ 'total' => 0, 'current' => $page, 'size' => $limit, 'list' => new Collection(), ]; return $this->access(function () use ($where, $fields, $page, $limit, $callback, $order) { return $this->model->findList($where, $fields, $page, $limit, $callback, $order); }, $failData); } /** * 根据条件查询列表[带分页 适用于后台] * * @param array $data 查询数据 * @param array $pageParams 分页参数 * @param callable|null $callback 复杂查询条件 使用闭包查询 * @return Paginator */ public function findListWithPaginate(array $data = [], array $pageParams = [], callable $callback = null): Paginator { return $this->model->findListWithPaginate($data, $pageParams, $callback); } /** * 根据主键 ID 查询 * * @param int $id ID * @param array $fields 要返回的字段,默认全部 * @return Mixed * @throws RepositoryException */ public function findById(int $id, array $fields = [], callable $callback = null) { return $this->access(function () use ($id, $fields, $callback) { return $this->model->findById($id, $fields, $callback); }, null); } /** * @param array $where * @param array $fields * @return array|Model|null * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException */ public function findOneByWhere(array $where, array $fields = []) { return $this->model->field($fields)->where($where)->find(); } /** * 创建 * * @param array $data 数据 * @return Model * @throws RepositoryException */ public function create(array $data): Model { return $this->access(function () use ($data) { return $this->model->create($data); }, new RepositoryException('创建失败')); } /** * 更新 * * @param array $data 数据 * @param array $where 条件 * @return bool|Exception * @throws RepositoryException */ public function update(array $data, array $where): bool { return $this->access(function () use ($data, $where) { return $this->model->where($where)->find()->save($data); }, new RepositoryException('更新失败')); } /** * 删除 * * @param array $where 删除条件 * @param bool $softDelete 是否软删除 默认false * @param string $softDeleteTime 删除时间 softDelete=true时有效 * @param string $softDeleteField 软删除字段 softDelete=true时有效 * @return bool * @throws RepositoryException */ public function delete(array $where, bool $softDelete = false, string $softDeleteTime = '', string $softDeleteField = 'deleted_at'): bool { return $this->access(function () use ($where, $softDelete, $softDeleteField, $softDeleteTime) { // 注意:如果model中引入了软删除trait,$softDelete又设置false 将无法正确删除 return $this->model->where($where) ->when($softDelete, function ($q) use ($softDeleteField, $softDeleteTime) { $softDeleteTime = $softDeleteTime ?: date('Y-m-d H:i:s'); $q->useSoftDelete($softDeleteField, $softDeleteTime); })->delete(); }, false); } /** * 排序 * * @param int $id 排序ID * @param string $type 排序类型 向上、向下 * @param int $num 移动位数 * @param string $listType 列表的排序类型 降序|升序 * @param array $where 额外条件 格式如: * $map[] = ['name','like','think']; * $map[] = ['status','=',1]; * @return array */ public function sort(int $id,string $type,int $num,string $listType, array $where = []): array { return $this->model->sort($id, $type, $num, $listType, $where); } /** * 日志记录 * * @param string $msg * @param Exception|null $e * @param string $level * @param string $channel */ public static function log(string $msg, Exception $e = null, string $level = 'error', string $channel = 'file') { if ($e != null) { $msg = sprintf("[%s]%s:%s %s", $msg, $e->getFile(), $e->getLine(), $e->getMessage()); } else { $msg = sprintf("%s", $msg); } Log::channel($channel)->$level($msg); } }