codeModel = new CodeModel(); $this->model = $this->createModel(); } abstract protected function createModel(); abstract protected function getCodeKeys(): array; abstract protected function getViewName(): string; abstract protected function getSearchKeys(): array; public function lists(): string { $codes = $this->codeModel->getCodeLists($this->getCodeKeys()); $sido = $this->model->getAreaList(); $bonbu = $this->model->getBonbuList(); $team = $this->model->getTeamList(); $user = $this->model->getUserList(); $this->data['codes'] = $codes; $this->data['sido'] = $sido; $this->data['bonbu'] = $bonbu; $this->data['team'] = $team; $this->data['user'] = $user; return view($this->getViewName(), $this->data); } public function getResultList() { $start = (int) $this->request->getGet('start') ?: 0; $end = (int) $this->request->getGet('length') ?: 10; $data = $this->buildSearchData(); $totalCount = $this->model->getTotalCount($data); $datas = $this->model->getResultList($start, $end, $data); return $this->response->setJSON([ 'recordsTotal' => $totalCount, 'recordsFiltered' => $totalCount, 'data' => $datas, ]); } public function excel() { try { $data = $this->buildSearchData(); $datas = $this->model->getExcelList($data); return $this->response->setJSON(['data' => $datas]); } catch (\Exception $e) { $e->getPrevious()->getTraceAsString(); } } /** * getSearchKeys()에 정의된 키만 GET에서 수집해서 배열로 반환 */ protected function buildSearchData(): array { $data = []; foreach ($this->getSearchKeys() as $key) { $rawValue = $this->request->getGet($key); $data[$key] = $this->normalizeSearchValue($key, $rawValue); } return $data; } /** * 공통 파라미터 정규화 * - null/공백은 빈 문자열로 통일 * - 문자열은 trim 처리 * - 날짜 키(date 포함)는 형식 검증 실패 시 빈 문자열로 처리 */ protected function normalizeSearchValue(string $key, $value) { if (is_array($value)) { return array_map(static function ($item) { if ($item === null) { return ''; } if (is_string($item)) { $item = trim($item); return $item === '' ? '' : $item; } return $item; }, $value); } if ($value === null) { return ''; } if (is_string($value)) { $value = trim($value); if ($value === '') { return ''; } } if ($this->isDateKey($key) && !$this->isValidDateValue((string) $value)) { return ''; } return $value; } /** * 날짜 성격 파라미터 판별 * 예: receipt_sdate, receipt_edate, complete_sdate, stat_complete_date 등 */ protected function isDateKey(string $key): bool { return strpos($key, 'date') !== false; } /** * 허용 날짜 형식 검증 * - YYYY-MM-DD * - YYYYMMDD */ protected function isValidDateValue(string $value): bool { if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value) === 1) { [$year, $month, $day] = explode('-', $value); return checkdate((int) $month, (int) $day, (int) $year); } if (preg_match('/^\d{8}$/', $value) === 1) { $year = substr($value, 0, 4); $month = substr($value, 4, 2); $day = substr($value, 6, 2); return checkdate((int) $month, (int) $day, (int) $year); } return false; } }