transaction = DBUtil::instance(); } /** * パラメータオブジェクト */ protected function getParam(): IParam { return $this->param; } /** * コントローラーの名前 * オーバーライドされることを想定 * 主に、Routeのドキュメント作成用 * * @return string */ public function name(): string { return "---未設定---"; } /** * コントローラーの説明 * オーバーライドされることを想定 * 主に、Routeのドキュメント作成用 * * @return string */ public function description(): string { return "---未設定---"; } /** * オーバーライド必要 * メインロジック * * @param Request $request * @return Response|JsonResponse|string */ protected function run(Request $request): Response|JsonResponse|BinaryFileResponse|string { return $this->successResponse(); } private function getRules() { return $this->getParam()->rules(); } public function entry(Request $request) { $this->setLogContext($request); try { $validator = Validator::make($request->all(), $this->getRules()); $validator->validate(); } catch (ValidationException $e) { logger("validate error", ['errors' => $e->errors(), 'request' => $request->all(), 'path' => $request->path()]); return $this->validateErrorResponse($e); } try { $this->validated = $validator->validated(); $this->getParam()->setData($this->validated); $this->authorize(); return $this->run($request); } catch (GeneralErrorMessageException $e) { return $this->failedResponse([], $e->getMessage()); } catch (AppCommonException $e) { logs()->error(sprintf("Appエラー:%s", $e->getMessage())); return $this->failedResponse(); } catch (ExclusiveException $e) { logs()->error(sprintf("排他エラー:%s", $e->getMessage())); return $this->exclusiveErrorResponse(); } catch (LogicException $e) { logs()->error([ sprintf("実装エラー:%s", $e->getMessage()), get_class($e), $e->getFile(), $e->getLine(), $request->all(), ]); logger(array_filter($e->getTrace(), function ($val, $key) { return $key <= 5; }, ARRAY_FILTER_USE_BOTH)); return $this->failedResponse(); } catch (ValidationException $e) { return $this->validateErrorResponse($e); } catch (HttpException $e) { if ($e->getStatusCode() === 401) { return $this->unAuthorizedResponse(); } throw e; } catch (Exception $e) { logs()->error([ sprintf("例外エラー:%s", $e->getMessage()), get_class($e), $e->getFile(), $e->getLine(), $request->all(), ]); logger(array_filter($e->getTrace(), function ($val, $key) { return $key <= 5; }, ARRAY_FILTER_USE_BOTH)); return $this->failedResponse(); } } protected function successResponse(array|object $data = [], array|string $messages = []) { return $this->setData($data) ->setMessages($messages) ->setResultCode(ResultCode::SECCESS) ->makeResponse(); } protected function failedResponse(array|object $data = [], array|string $messages = []) { return $this->setData($data) ->setMessages($messages) ->setResultCode(ResultCode::FAILED) ->makeResponse(); } protected function unAuthorizedResponse(array|object $data = [], array|string $messages = []) { return $this->setData($data) ->setMessages($messages) ->setResultCode(ResultCode::UNAUTHORIZED) ->makeResponse(); } protected function exclusiveErrorResponse(array|object $data = [], array|string $messages = []) { return $this->setData($data) ->setMessages($messages) ->setResultCode(ResultCode::EXCLUSIVE_ERROR) ->makeResponse(); } protected function validateErrorResponse(ValidationException|array $exception, string|null $generalMessage = null) { $errorMessages = []; $general = null; if ($exception instanceof ValidationException) { foreach ($exception->errors() as $key => $m) { $errorMessages[$key] = $m[0]; } } if (is_array($exception)) { $errorMessages = $exception; } $general = $generalMessage ?? data_get($errorMessages, self::COL_NAME_GENERAL_MESSAGE); return $this->setData([]) ->setMessages($errorMessages) ->setGeneralMessage($general) ->setResultCode(ResultCode::FAILED) ->makeResponse(); } private function makeResponse() { if ($this->resultCode === null) { abort(403); } $ret = []; Arr::set($ret, self::COL_NAME_RESULT_CODE, $this->resultCode->value); if ($this->data !== null) { Arr::set($ret, self::COL_NAME_DATA, $this->data); } if ($this->messages !== null) { Arr::set($ret, self::COL_NAME_MESSAGES . "." . self::COL_NAME_ERRORS, $this->messages); } if ($this->generalMessage !== null) { Arr::set($ret, self::COL_NAME_MESSAGES . "." . self::COL_NAME_GENERAL_MESSAGE, $this->generalMessage); } if ($this->emailId !== null) { Arr::set($ret, self::COL_NAME_MESSAGES . "." . self::COL_NAME_EMAIL_ID, $this->emailId); } if (request()->wantsJson()) { return response() ->json($ret) ->withHeaders($this->makeHeader()); } else { abort(500); } } private function makeHeader(): array { $header = []; $user = Auth::user(); if ($user) { $header["App-User-Auth"] = sprintf("%d,%d", $user->id, $user->role->value); } else { $header["App-User-Auth"] = 'none'; } return $header; } // 以下 認可関係 protected array|null $roleAllow = null; protected array|null $roleDisallow = null; protected array|null $customAllow = null; protected function roleAllow(UserRole $role) { $this->roleAllow = []; foreach (UserRole::cases() as $ele) { if ($role->value <= $ele->value) { $this->roleAllow[] = $ele; } } } private function authorize() { if (!Auth::check()) { return; } $role = Auth::user()->role; if (!$this->canAccess($role)) { abort(401); } } public function canAccess(UserRole $role) { if (is_array($this->roleAllow) && !in_array($role, $this->roleAllow)) { return false; } if (is_array($this->roleDisallow) && in_array($role, $this->roleDisallow)) { return false; } return $this->canCustomAccess(); } public function canCustomAccess(): bool { if (Auth::user()->role === UserRole::SUPER_ADMIN) { return true; } if ($this->customAllow === null) { return true; } $myCustoms = Auth::user()->contract->custom(); foreach ($this->customAllow as $targetCustom) { if (in_array($targetCustom, $myCustoms, true)) { return true; } } return false; } // 返却用データの登録 protected function setEmailId(int $emailId) { $this->emailId = $emailId; return $this; } protected function setMessages(array|string $messages) { if (is_array($messages)) { $this->messages = $messages; } else { $this->setGeneralMessage($messages); } return $this; } protected function setGeneralMessage(string|null $generalMessage) { $this->generalMessage = $generalMessage; return $this; } protected function setData($data) { $this->data = $data; return $this; } protected function setResultCode(ResultCode $resultCode) { $this->resultCode = $resultCode; return $this; } protected function setLogContext(Request $request) { Log::withContext([ '__requestUuid__' => strval(Str::uuid()), '__userId__' => Auth::id(), '__path__' => $request->path(), ]); } }