From f0511fbf56953719d26606a2ef52e04697204e15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=EC=A4=80=ED=9D=A0?= Date: Fri, 28 Nov 2025 15:05:06 +0900 Subject: [PATCH] dbmsv4 init...1 --- app/Config/Constants.php | 8 +- app/Controllers/AbstractCRUDController.php | 61 ++++-------- .../Admin/Equipment/ServerPartController.php | 1 - app/Controllers/Auth/AuthController.php | 28 +++--- app/Forms/Equipment/ServerPartForm.php | 4 +- app/Helpers/CommonHelper.php | 2 +- app/Helpers/Equipment/ServerPartHelper.php | 6 ++ app/Language/en/Equipment/ServerPart.php | 2 +- app/Services/CommonService.php | 96 +++++++++++-------- app/Services/Equipment/ServerPartService.php | 13 ++- 10 files changed, 116 insertions(+), 105 deletions(-) diff --git a/app/Config/Constants.php b/app/Config/Constants.php index 350bced..36c8c43 100644 --- a/app/Config/Constants.php +++ b/app/Config/Constants.php @@ -278,11 +278,11 @@ define('AUDIOS', [ //Layout관련 define('KEYWORD', '일본IDC 일본서버 일본 서버 일본호스팅 서버호스팅 디도스 공격 해외 호스팅 DDOS 방어 ddos 의뢰 디도스 보안 일본 단독서버 가상서버'); define('LAYOUTS', [ - 'empty' => [ + 'auth' => [ 'title' => KEYWORD, - 'path' => 'empty', - 'layout' => 'layouts' . DIRECTORY_SEPARATOR . 'empty', - 'template' => 'templates' . DIRECTORY_SEPARATOR . 'empty', + 'path' => 'auth', + 'layout' => 'layouts' . DIRECTORY_SEPARATOR . 'auth', + 'template' => 'templates' . DIRECTORY_SEPARATOR . 'auth', 'metas' => [ '', '', diff --git a/app/Controllers/AbstractCRUDController.php b/app/Controllers/AbstractCRUDController.php index d756dab..fc6e2c9 100644 --- a/app/Controllers/AbstractCRUDController.php +++ b/app/Controllers/AbstractCRUDController.php @@ -74,14 +74,7 @@ abstract class AbstractCRUDController extends AbstractWebController // --- 수정 (Modify) --- protected function modify_form_process($uid): CommonEntity { - if (!$uid) { - throw new \Exception("{$this->getTitle()}에 번호가 정의 되지 않았습니다."); - } - $entity = $this->service->getEntity($uid); - if (!$entity instanceof CommonEntity) { - throw new \Exception("{$uid}에 해당하는 {$this->getTitle()}을 찾을수 없습니다."); - } - return $entity; + return $this->service->getEntity($uid); } protected function modify_form_result_process(string $action): string|RedirectResponse @@ -92,12 +85,10 @@ abstract class AbstractCRUDController extends AbstractWebController final public function modify_form($uid): string|RedirectResponse { try { - $entity = $this->modify_form_process($uid); - // 💡 동적으로 가져온 Entity 클래스 이름으로 instanceof 검사 - $entityClass = $this->service->getEntityClass(); - if (!$entity instanceof $entityClass) { - throw new RuntimeException(__METHOD__ . "에서 오류발생:Return Type은 {$entityClass}만 가능"); + if (!$uid) { + throw new \Exception("{$this->getTitle()}에 번호가 정의 되지 않았습니다."); } + $entity = $this->modify_form_process($uid); $this->addViewDatas('entity', $entity); $action = __FUNCTION__; //FormService에서 필요한 기존 데이터를 $entity에서 추출해서 넘김 @@ -110,6 +101,7 @@ abstract class AbstractCRUDController extends AbstractWebController protected function modify_process($uid): CommonEntity { + $entity = $this->service->getEntity($uid); // POST 데이터를 DTO 객체로 변환 $dto = $this->service->createDTO($this->request->getPost()); return $this->service->modify($uid, $dto); @@ -124,14 +116,12 @@ abstract class AbstractCRUDController extends AbstractWebController final public function modify($uid): string|RedirectResponse { try { + if (!$uid) { + throw new \Exception("{$this->getTitle()}에 번호가 정의 되지 않았습니다."); + } $action = __FUNCTION__; $this->action_init_process($action); $entity = $this->modify_process($uid); - // 💡 동적으로 가져온 Entity 클래스 이름으로 instanceof 검사 - $entityClass = $this->service->getEntityClass(); - if (!$entity instanceof $entityClass) { - throw new RuntimeException(__METHOD__ . "에서 오류발생:Return Type은 {$entityClass}만 가능"); - } $this->addViewDatas('entity', $entity); return $this->modify_result_process($entity); } catch (\Throwable $e) { @@ -153,12 +143,12 @@ abstract class AbstractCRUDController extends AbstractWebController final public function delete($uid): RedirectResponse { try { - $entity = $this->delete_process($uid); - // 💡 동적으로 가져온 Entity 클래스 이름으로 instanceof 검사 - $entityClass = $this->service->getEntityClass(); - if (!$entity instanceof $entityClass) { - throw new RuntimeException(__METHOD__ . "에서 오류발생:Return Type은 {$entityClass}만 가능"); + if (!$uid) { + throw new \Exception("{$this->getTitle()}에 번호가 정의 되지 않았습니다."); } + $entity = $this->service->getEntity($uid); + //Delete처리 + $entity = $this->delete_process($uid); return $this->delete_result_process($entity); } catch (\Throwable $e) { return $this->action_redirect_process('error', "{$this->getTitle()}에서 삭제 오류:" . $e->getMessage()); @@ -169,32 +159,23 @@ abstract class AbstractCRUDController extends AbstractWebController protected function view_process($uid): CommonEntity { - if (!$uid) { - throw new \Exception("{$this->getTitle()}에 번호가 정의 되지 않았습니다."); - } - $entity = $this->service->getEntity($uid); - if (!$entity instanceof CommonEntity) { - throw new \Exception("{$uid}에 해당하는 {$this->getTitle()}을 찾을수 없습니다."); - } - return $entity; + return $this->service->getEntity($uid); } - protected function view_result_process(string $action): string { return $this->action_render_process($action, $this->getViewDatas(), $this->request->getVar('ActionTemplate')); } - final public function view($uid): string|RedirectResponse { try { - $action = __FUNCTION__; - $this->action_init_process($action); - $entity = $this->view_process($uid); - // 💡 동적으로 가져온 Entity 클래스 이름으로 instanceof 검사 - $entityClass = $this->service->getEntityClass(); - if (!$entity instanceof $entityClass) { - throw new RuntimeException(__METHOD__ . "에서 오류발생:Return Type은 {$entityClass}만 가능"); + if (!$uid) { + throw new \Exception("{$this->getTitle()}에 번호가 정의 되지 않았습니다."); } + //View처리 + $entity = $this->view_process($uid); + $action = __FUNCTION__; + //FormService에서 필요한 기존 데이터를 $entity에서 추출해서 넘김 + $this->action_init_process($action, $entity->toArray()); $this->addViewDatas('entity', $entity); return $this->view_result_process($action); } catch (\Throwable $e) { diff --git a/app/Controllers/Admin/Equipment/ServerPartController.php b/app/Controllers/Admin/Equipment/ServerPartController.php index e43e18d..3b279ac 100644 --- a/app/Controllers/Admin/Equipment/ServerPartController.php +++ b/app/Controllers/Admin/Equipment/ServerPartController.php @@ -2,7 +2,6 @@ namespace App\Controllers\Admin\Equipment; -use App\Entities\Equipment\ServerPartEntity; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; use Psr\Log\LoggerInterface; diff --git a/app/Controllers/Auth/AuthController.php b/app/Controllers/Auth/AuthController.php index e9ff15b..23f2295 100644 --- a/app/Controllers/Auth/AuthController.php +++ b/app/Controllers/Auth/AuthController.php @@ -11,20 +11,19 @@ use Psr\Log\LoggerInterface; abstract class AuthController extends AbstractWebController { + private $_layout = 'auth'; + protected $layouts = []; public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger) { parent::initController($request, $response, $logger); - $this->addActionPaths('auth'); - } - final protected function getLayout(): string - { - return 'auth'; + $this->addActionPaths($this->_layout); + $this->layouts = LAYOUTS[$this->_layout]; } protected function action_init_process(string $action, array $formDatas = []): void { - $this->service->action_init_process($action); - parent::action_init_process($action); - $this->addViewDatas('layout', $this->getLayout()); + $this->service->action_init_process($action, $formDatas); + parent::action_init_process($action, $formDatas); + $this->addViewDatas('layout', $this->layouts); $this->addViewDatas('helper', $this->service->getHelper()); $this->addViewDatas('formFields', $this->service->getFormService()->getFormFields()); $this->addViewDatas('formRules', $this->service->getFormService()->getFormRules()); @@ -48,9 +47,13 @@ abstract class AuthController extends AbstractWebController abstract protected function login_process(): UserEntity; final public function login(): RedirectResponse { - $this->login_process(); - $redirect_url = $this->getAuthContext()->popPreviousUrl() ?? implode(DIRECTORY_SEPARATOR, $this->getActionPaths()); - return redirect()->to($redirect_url)->with('message', MESSAGES['LOGIN']); + try { + $this->login_process(); + $redirect_url = $this->getAuthContext()->popPreviousUrl() ?? implode(DIRECTORY_SEPARATOR, $this->getActionPaths()); + return redirect()->to($redirect_url)->with('message', MESSAGES['LOGIN']); + } catch (\Throwable $e) { + return redirect()->back()->withInput()->with('message', "로그인 중 오류발생:" . $e->getMessage()); + } } //로그아웃 abstract protected function logout_process(): void; @@ -62,8 +65,7 @@ abstract class AuthController extends AbstractWebController $redirect_url = $this->getAuthContext()->popPreviousUrl() ?? "/"; return redirect()->route($redirect_url)->with('message', MESSAGES['LOGOUT']); } catch (\Throwable $e) { - log_message("error", $e->getMessage()); - return redirect()->back()->withInput()->with('message', "로그아웃 중 오류가 발생했습니다."); + return redirect()->back()->withInput()->with('message', "로그아웃 중 오류발생:" . $e->getMessage()); } } } diff --git a/app/Forms/Equipment/ServerPartForm.php b/app/Forms/Equipment/ServerPartForm.php index 99b0bb2..3ce71c5 100644 --- a/app/Forms/Equipment/ServerPartForm.php +++ b/app/Forms/Equipment/ServerPartForm.php @@ -50,12 +50,14 @@ class ServerPartForm extends EquipmentForm foreach (SERVERPART['ALL_PARTTYPES'] as $type) { $partService = $this->getPartService($type); $tempOptions[$type] = [lang("{$this->getAttribute('class_path')}.TYPE.{$type}") . " 선택"]; - foreach ($partService->getEntities(['status' => STATUS['AVAILABLE']]) as $tempEntity) { + foreach ($this->getFormOption_process($partService, $action, $field, $formDatas) as $tempEntity) { $tempOptions[$type][$tempEntity->getPK()] = $tempEntity->getTitle(); // $options['attributes'][$type][$tempEntity->getPK()] = ['data-role' => implode(DEFAULTS['DELIMITER_ROLE'], $tempEntity->getRole())]; } } $options['options'] = $tempOptions; + // dd($formDatas); + // dd($options); break; case 'serverinfo_uid': foreach ($this->getFormOption_process(service('equipment_serverservice'), $action, $field, $formDatas) as $tempEntity) { diff --git a/app/Helpers/CommonHelper.php b/app/Helpers/CommonHelper.php index 20d35d8..c4288a8 100644 --- a/app/Helpers/CommonHelper.php +++ b/app/Helpers/CommonHelper.php @@ -186,7 +186,7 @@ abstract class CommonHelper if (!array_key_exists($value, $viewDatas['formOptions'][$field]['options'])) { throw new \Exception(__METHOD__ . "에서 오류발생: {$field}에서 {$value}에 해당하는 값이 존재하지 않습니다."); } - $value = !$value ? "" : $viewDatas['formOptions'][$field]['options'][$value]; + $value = $viewDatas['formOptions'][$field]['options'][$value]; } } break; diff --git a/app/Helpers/Equipment/ServerPartHelper.php b/app/Helpers/Equipment/ServerPartHelper.php index 4b7e13a..e0dfc5d 100644 --- a/app/Helpers/Equipment/ServerPartHelper.php +++ b/app/Helpers/Equipment/ServerPartHelper.php @@ -38,6 +38,12 @@ class ServerPartHelper extends EquipmentHelper public function getFieldView(string $field, mixed $value, array $viewDatas, array $extras = []): string|null { switch ($field) { + case 'part_uid': + if (!array_key_exists($value, $viewDatas['formOptions'][$field]['options'][$viewDatas['entity']->getType()])) { + throw new \Exception(__METHOD__ . "에서 오류발생: {$field}에서 {$value}에 해당하는 값이 존재하지 않습니다."); + } + $value = $viewDatas['formOptions'][$field]['options'][$viewDatas['entity']->getType()][$value]; + break; case 'SERVER': $value = form_label( sprintf( diff --git a/app/Language/en/Equipment/ServerPart.php b/app/Language/en/Equipment/ServerPart.php index be15a50..a2c044d 100644 --- a/app/Language/en/Equipment/ServerPart.php +++ b/app/Language/en/Equipment/ServerPart.php @@ -1,6 +1,6 @@ "서버장비정보", + 'title' => "서버파트정보", 'label' => [ 'part_uid' => "부품정보", 'clientinfo_uid' => "고객번호", diff --git a/app/Services/CommonService.php b/app/Services/CommonService.php index 9e5b3de..6cb454a 100644 --- a/app/Services/CommonService.php +++ b/app/Services/CommonService.php @@ -4,6 +4,7 @@ namespace App\Services; use App\DTOs\CommonDTO; use App\Entities\CommonEntity; +use App\Libraries\AuthContext; use App\Models\CommonModel; use CodeIgniter\Database\Exceptions\DatabaseException; use CodeIgniter\Validation\Exceptions\ValidationException; @@ -15,6 +16,7 @@ use RuntimeException; */ abstract class CommonService { + private ?AuthContext $_authContext = null; private array $_classPaths = []; protected $title = null; protected function __construct(protected CommonModel $model) {} @@ -24,6 +26,13 @@ abstract class CommonService abstract public function getEntityClass(): string; abstract public function getFormService(): mixed; abstract public function getHelper(): mixed; + final public function getAuthContext(): AuthContext + { + if ($this->_authContext === null) { + $this->_authContext = new AuthContext(); + } + return $this->_authContext; + } final protected function addClassPaths(string $path): void { $this->_classPaths[] = $path; @@ -42,6 +51,10 @@ abstract class CommonService * 단일 엔티티를 조회합니다. * @return CommonEntity|null CommonEntity 인스턴스 또는 찾지 못했을 경우 null */ + protected function getEntity_process(CommonEntity $entity): CommonEntity + { + return $entity; + } public function getEntity(string|int|array $where, ?string $message = null): ?CommonEntity { try { @@ -49,8 +62,10 @@ abstract class CommonService if (!$entity) { return null; } - if (!$entity instanceof CommonEntity) { - throw new \Exception(__METHOD__ . "에서 결과값 오류발생:\n" . var_export($entity, true)); + // 💡 동적으로 가져온 Entity 클래스 이름으로 instanceof 검사 + $entityClass = $this->getEntityClass(); + if (!$entity instanceof $entityClass) { + throw new RuntimeException(__METHOD__ . "에서 오류발생:Return Type은 {$entityClass}만 가능:\n" . var_export($entity, true)); } return $this->getEntity_process($entity); } catch (DatabaseException $e) { @@ -71,11 +86,30 @@ abstract class CommonService throw new \Exception($errorMessage, $e->getCode(), $e); } } - public function getEntities(?array $where = null, array $columns = ['*']): array + /** + * 엔티티 배열 조회합니다. + * @return CommonEntity|null CommonEntity 인스턴스 또는 찾지 못했을 경우 null + */ + protected function getEntities_process(mixed $where = null, array $columns = ['*'], array $entities = []): array + { + if ($where) { + $this->model->where($where); + } + /** @var array<\App\Entities\CommonEntity> $results */ + $results = $this->model->select(implode(',', $columns))->findAll(); + if (is_null($results)) { + $results = []; + } + foreach ($results as $entity) { + $entities[$entity->getPK()] = $this->getEntity_process($entity); + } + log_message('debug', $this->model->getLastQuery()); + return $entities; + } + public function getEntities(?array $where = null, array $columns = ['*'], array $entities = []): array { try { - $entities = $this->getEntities_process($where, $columns); - log_message('debug', $this->model->getLastQuery()); + $entities = $this->getEntities_process($where, $columns, $entities); return $entities; } catch (DatabaseException $e) { $errorMessage = sprintf( @@ -95,25 +129,6 @@ abstract class CommonService throw new \Exception($errorMessage, $e->getCode(), $e); } } - //Entity관련 - protected function getEntity_process(CommonEntity $entity): CommonEntity - { - return $entity; - } - - //entities를 가져오는 조건 - protected function getEntities_process(mixed $where = null, array $columns = ['*']): array - { - if ($where) { - $this->model->where($where); - } - $entities = []; - foreach ($this->model->select(implode(',', $columns))->findAll() as $entity) { - $entities[$entity->getPK()] = $this->getEntity_process($entity); - } - return $entities; - } - //CURD 결과처리용 protected function handle_save_result(mixed $result, int|string $uid): int|string { @@ -159,6 +174,10 @@ abstract class CommonService //생성용 protected function create_process(array $formDatas): CommonEntity { + //FormData 검증 + if (!$this->getFormService()->validate($formDatas)) { + throw new ValidationException(implode("\n", service('validation')->getErrors())); + } // 💡 동적으로 가져온 Entity 클래스 이름으로 instanceof 검사 $entityClass = $this->getEntityClass(); $entity = new $entityClass($formDatas); @@ -178,13 +197,9 @@ abstract class CommonService if (!$dto instanceof $dtoClass) { throw new RuntimeException(__METHOD__ . "에서 오류발생: " . get_class($dto) . "는 사용할 수 없습니다. ({$dtoClass} 필요)"); } - $formDatas = $dto->toArray(); - if (!$this->getFormService()->validate($formDatas)) { - throw new ValidationException(implode("\n", service('validation')->getErrors())); - } // NOTE: create_process에서 엔티티를 생성할 때, 자동 증가(AUTO_INCREMENT) 필드는 // DB가 처리하도록 NULL이나 빈 값(0)으로 두는 것이 일반적입니다. - $entity = $this->create_process($formDatas); + $entity = $this->create_process($dto->toArray()); // 트랜잭션 완료 및 커밋 $db->transComplete(); return $entity; @@ -205,6 +220,11 @@ abstract class CommonService //수정용 protected function modify_process(string|int $uid, array $formDatas): CommonEntity { + //FormData 검증 + if (!$this->getFormService()->validate($formDatas)) { + throw new ValidationException(implode("\n", service('validation')->getErrors())); + } + //기존 Entity가져오기 $entity = $this->getEntity($uid); if (!$entity) { throw new \Exception(__METHOD__ . "에서 오류발생: {$uid}에 해당하는 정보을 찾을수 없습니다."); @@ -238,11 +258,7 @@ abstract class CommonService if (!$dto instanceof $dtoClass) { throw new RuntimeException(__METHOD__ . "에서 오류발생: " . get_class($dto) . "는 사용할 수 없습니다. ({$dtoClass} 필요)"); } - $formDatas = $dto->toArray(); - if (!$this->getFormService()->validate($formDatas)) { - throw new ValidationException(implode("\n", service('validation')->getErrors())); - } - $entity = $this->modify_process($uid, $formDatas); + $entity = $this->modify_process($uid, $dto->toArray()); // 트랜잭션 완료 및 커밋 $db->transComplete(); return $entity; @@ -278,14 +294,10 @@ abstract class CommonService if (!$dto instanceof $dtoClass) { throw new RuntimeException(__METHOD__ . "에서 오류발생: " . get_class($dto) . "는 사용할 수 없습니다. ({$dtoClass} 필요)"); } - $formDatas = $dto->toArray(); - if (!$this->getFormService()->validate($formDatas)) { - throw new ValidationException(implode("\n", service('validation')->getErrors())); - } //일괄작업처리 $entities = []; foreach ($uids as $uid) { - $entities[] = $this->batchjob_process($uid, $formDatas); + $entities[] = $this->batchjob_process($uid, $dto->toArray()); } // 트랜잭션 완료 및 커밋 $db->transComplete(); @@ -314,6 +326,12 @@ abstract class CommonService if (!$entity) { throw new \Exception(__METHOD__ . "에서 오류발생: {$uid}에 해당하는 정보을 찾을수 없습니다."); } + // 💡 동적으로 가져온 Entity 클래스 이름으로 instanceof 검사 + $entityClass = $this->getEntityClass(); + if (!$entity instanceof $entityClass) { + throw new RuntimeException(__METHOD__ . "에서 오류발생:Return Type은 {$entityClass}만 가능"); + } + //삭제 $result = $this->model->delete($entity->getPK()); log_message('debug', $this->model->getLastQuery()); if ($result === false) { diff --git a/app/Services/Equipment/ServerPartService.php b/app/Services/Equipment/ServerPartService.php index ddbb718..89395f5 100644 --- a/app/Services/Equipment/ServerPartService.php +++ b/app/Services/Equipment/ServerPartService.php @@ -122,12 +122,15 @@ class ServerPartService extends EquipmentService } //각 파트정보 가져오기 $partEntity = $this->getPartService($formDatas['type'])->getEntity($formDatas['part_uid']); - //서버파트정보 Title 설정용 + //해당 파트정보 Title 설정용 $formDatas['title'] = $partEntity->getTitle(); + //서버파트 생성 $entity = parent::create_process($formDatas); if (!$entity instanceof ServerPartEntity) { throw new RuntimeException(__METHOD__ . "에서 오류발생:Return Type은 ServerPartEntity만 가능"); } + //해당 파트별 설정 수정 + $this->getPartService($entity->getType())->attachToServerPart($entity); return $entity; } protected function modify_process($uid, array $formDatas): ServerPartEntity @@ -137,8 +140,9 @@ class ServerPartService extends EquipmentService } //각 파트정보 가져오기 $partEntity = $this->getPartService($formDatas['type'])->getEntity($formDatas['part_uid']); - //서버파트정보 Title 설정용 + //해당 파트정보 Title 설정용 $formDatas['title'] = $partEntity->getTitle(); + //서버파트 수정 $entity = parent::modify_process($uid, $formDatas); if (!$entity instanceof ServerPartEntity) { throw new RuntimeException(__METHOD__ . "에서 오류발생:Return Type은 ServerPartEntity만 가능"); @@ -149,7 +153,7 @@ class ServerPartService extends EquipmentService //FormFilter 조건절 처리 //검색어조건절처리 - //서버추가시 서버파트 자동추가용 + //서버추가시 기본파트 자동추가용 public function attachToServer(ServerEntity $serverEntity): void { //*서버의 Title 대소문자구분 필요->서버의 Title로 구분해서 기본부품 추가 @@ -176,11 +180,10 @@ class ServerPartService extends EquipmentService $fields = array_keys($formDatas); $this->getFormService()->setFormFields($fields); $this->getFormService()->setFormRules('create', $fields); - $entity = $this->create($this->createDTO($formDatas)); + $entity = $this->create_process($formDatas); if (!$entity instanceof ServerPartEntity) { throw new \Exception(__METHOD__ . "에서 오류발생: Return Type은 ServerPartEntity만 가능합니다."); } - $this->getPartService($entity->getType())->attachToServerPart($entity); } } }