middleware('front'); $this->host = env('MOVIE_API'); $this->companyModel = $companyModel; } /** * 영화사 목록 (DB 조회) * @method GET * @see /movie/company */ public function index(Request $request) { $rules = [ 'page' => 'nullable|numeric', 'keyword' => 'nullable|string|max:100', 'ceo' => 'nullable|string|max:30' ]; $attributes = [ 'page' => '페이지 번호', 'keyword' => '영화사명', 'ceo' => '대표자명' ]; $message = [ 'page.numeric' => '페이지 번호는 숫자여야 합니다.', 'keyword.max' => '영화사명 최대 글자는 100자 입니다.', 'ceo.max' => '대표자명 최대 글자는 30자 입니다.' ]; // 검색 유효성 검사 Validator::make($request->all(), $rules, $message, $attributes)->validated(); $params = SearchData::fromRequest($request); $data = $this->companyModel->list($params); // 상세 보기 URL 세팅 $queryString = $request->getQueryString(); foreach ($data->list as $row) { $row->viewURL = route('movie.company.show', base64_encode($row->companyCd)); if ($queryString) { $row->viewURL .= ('?' . $queryString); } } return view(layout('movie.company.index'), [ 'keyword' => $request->get('keyword'), 'ceo' => $request->get('ceo'), 'total' => $data->total, 'companies' => $data->list ]); } /** * 영화사 상세 보기 (DB 우선 + 캐시, 미수집 시 API 폴백) * @method GET * @see /movie/company/{company_cd} */ public function show(string $base64, Request $request) { try { if(!$base64) { throw new Exception('잘못된 접근입니다. [1]'); } $companyCd = base64_decode($base64); if(!$companyCd) { throw new Exception('잘못된 접근입니다. [2]'); } $listURL = route('movie.company.index'); if($queryString = $request->getQueryString()) { $listURL .= ('?' . $queryString); } // 캐시 → DB → crawler API 폴백 순으로 조회 $cacheKey = ('movie:company:' . $companyCd); $info = Cache::get($cacheKey); if (!$info) { $info = $this->companyModel->info($companyCd); // DB 미수집이면 crawler API 폴백 (수집은 cron 이 채움) if (!$info) { $info = $this->fetchFromApi($companyCd); } if ($info && !empty($info->companyCd)) { Cache::put($cacheKey, $info, CACHE_EXPIRE_TIME); } } if(!$info || empty($info->companyCd)) { throw new Exception('요청한 정보가 없습니다.'); } $companyNm = $info->companyNm; if(!empty($info->companyNmEn)) { $companyNm .= (' (' . $info->companyNmEn . ')'); } return view(layout('movie.company.show'), [ 'companyNm' => $companyNm, 'info' => $info, 'listURL' => $listURL ]); } catch(Exception $e) { abort($e->getCode() ?: 500, $e->getMessage()); } } /** * DB 미수집 영화사를 crawler API 로 즉석 조회 (폴백) */ private function fetchFromApi(string $companyCd): ?object { try { $params = new CompanyParams(); $params->companyCd = $companyCd; $response = Http::timeout(5)->get($this->host . COMPANY_INFO, $params->toArray()); } catch (ConnectionException) { return null; } if (!$response->ok()) { return null; } $data = json_decode($response->body()); return ($data->info ?? null); } }