dbmsv4 init...5

This commit is contained in:
최준흠 2026-03-11 12:43:39 +09:00
parent 43dd7caf02
commit c95b8c8dac
19 changed files with 237 additions and 202 deletions

View File

@ -25,11 +25,11 @@ class BoardEntity extends CommonEntity
}
public function getUserUid(): ?int
{
return $this->user_uid;
return $this->user_uid === null ? null : (int) $this->user_uid;
}
public function getWorkerUid(): ?int
{
return $this->worker_uid;
return $this->worker_uid === null ? null : (int) $this->worker_uid;
}
public function getCaregory(): string
{
@ -37,6 +37,6 @@ class BoardEntity extends CommonEntity
}
public function getContent(): ?string
{
return $this->category;
return $this->content;
}
}

View File

@ -17,6 +17,6 @@ abstract class CustomerEntity extends CommonEntity
final public function getUserUid(): ?int
{
return $this->user_uid;
return $this->user_uid === null ? null : (int) $this->user_uid;
}
}

View File

@ -29,11 +29,11 @@ class ServiceEntity extends CustomerEntity
}
public function getClientInfoUid(): ?int
{
return $this->clientinfo_uid;
return $this->clientinfo_uid === null ? null : (int) $this->clientinfo_uid;
}
public function getServerInfoUid(): ?int
{
return $this->serverinfo_uid;
return $this->serverinfo_uid === null ? null : (int) $this->serverinfo_uid;
}
//기본기능용
public function getCode(): string

View File

@ -27,7 +27,7 @@ abstract class WalletEntity extends CustomerEntity
final public function getClientInfoUid(): ?int
{
return $this->clientinfo_uid;
return $this->clientinfo_uid === null ? null : (int) $this->clientinfo_uid;
}
final public function getAmount(): int

View File

@ -21,15 +21,15 @@ class CHASSISEntity extends EquipmentEntity
}
public function getCPUInfoUid(): ?int
{
return $this->cpuinfo_uid;
return $this->cpuinfo_uid === null ? null : (int) $this->cpuinfo_uid;
}
public function getRAMInfoUid(): ?int
{
return $this->raminfo_uid;
return $this->raminfo_uid === null ? null : (int) $this->raminfo_uid;
}
public function getDISKInfoUid(): ?int
{
return $this->diskinfo_uid;
return $this->diskinfo_uid === null ? null : (int) $this->diskinfo_uid;
}
//기본기능
public function getPrice(): int
@ -46,7 +46,7 @@ class CHASSISEntity extends EquipmentEntity
}
public function getAvailable(): int
{
return $this->getStock() - $this->getUsed();
return (int) ($this->getStock() - $this->getUsed());
}
public function getCPUCnt(): int
{

View File

@ -25,19 +25,19 @@ class ServerEntity extends EquipmentEntity
}
final public function getClientInfoUid(): ?int
{
return $this->clientinfo_uid;
return $this->clientinfo_uid === null ? null : (int) $this->clientinfo_uid;
}
final public function getServiceInfoUid(): ?int
{
return $this->serviceinfo_uid;
return $this->serviceinfo_uid === null ? null : (int) $this->serviceinfo_uid;
}
final public function getChassisInfoUid(): int
{
return $this->chassisinfo_uid;
return $this->chassisinfo_uid === null ? null : (int) $this->chassisinfo_uid;
}
final public function getSwitchInfoUid(): ?int
{
return $this->switchinfo_uid;
return $this->switchinfo_uid === null ? null : (int) $this->switchinfo_uid;
}
//기본기능용

View File

@ -29,19 +29,19 @@ class ServerPartEntity extends EquipmentEntity
}
public function getClientInfoUid(): ?int
{
return $this->clientinfo_uid;
return $this->clientinfo_uid === null ? null : (int) $this->clientinfo_uid;
}
public function getServiceInfoUid(): ?int
{
return $this->serviceinfo_uid;
return $this->serviceinfo_uid === null ? null : (int) $this->serviceinfo_uid;
}
public function getServerInfoUid(): int
{
return $this->serverinfo_uid;
return $this->serverinfo_uid === null ? null : (int) $this->serverinfo_uid;
}
public function getPartUid(): ?int
{
return $this->part_uid;
return $this->part_uid === null ? null : (int) $this->part_uid;
}
//기본기능용
public function getCustomTitle(): string

View File

@ -19,6 +19,6 @@ class MylogEntity extends CommonEntity
//Common Function
public function getUserUid(): ?int
{
return $this->user_uid;
return $this->user_uid === null ? null : (int) $this->user_uid;
}
}

View File

@ -24,15 +24,15 @@ class CSEntity extends PartType2Entity
//기본기능
final public function getClientInfoUid(): ?int
{
return $this->clientinfo_uid;
return $this->clientinfo_uid === null ? null : (int) $this->clientinfo_uid;
}
final public function getServiceInfoUid(): ?int
{
return $this->serviceinfo_uid;
return $this->serviceinfo_uid === null ? null : (int) $this->serviceinfo_uid;
}
final public function getServerInfoUid(): ?int
{
return $this->serverinfo_uid;
return $this->serverinfo_uid === null ? null : (int) $this->serverinfo_uid;
}
public function getIP(): string
{

View File

@ -17,6 +17,6 @@ class DISKEntity extends PartType1Entity
public function getFormat(): int
{
return $this->format ?? 0;
return (int) $this->format ?? 0;
}
}

View File

@ -23,23 +23,23 @@ class IPEntity extends PartType3Entity
}
public function getLineInfoUID(): int
{
return $this->lineinfo_uid;
return $this->lineinfo_uid === null ? null : (int) $this->lineinfo_uid;
}
public function getOldClientInfoUID(): ?int
{
return $this->old_clientinfo_uid;
return $this->old_clientinfo_uid === null ? null : (int) $this->old_clientinfo_uid;
}
final public function getClientInfoUid(): ?int
{
return $this->clientinfo_uid;
return $this->clientinfo_uid === null ? null : (int) $this->clientinfo_uid;
}
final public function getServiceInfoUid(): ?int
{
return $this->serviceinfo_uid;
return $this->serviceinfo_uid === null ? null : (int) $this->serviceinfo_uid;
}
final public function getServerInfoUid(): ?int
{
return $this->serverinfo_uid;
return $this->serverinfo_uid === null ? null : (int) $this->serverinfo_uid;
}
//기본기능
public function getIP(): string

View File

@ -19,6 +19,6 @@ class PartType1Entity extends PartEntity
}
final public function getAvailable(): int
{
return $this->getStock() - $this->getUsed();
return (int) ($this->getStock() - $this->getUsed());
}
}

View File

@ -21,15 +21,15 @@ class SWITCHEntity extends PartType3Entity
}
final public function getClientInfoUid(): ?int
{
return $this->clientinfo_uid;
return $this->clientinfo_uid === null ? null : (int) $this->clientinfo_uid;
}
final public function getServiceInfoUid(): ?int
{
return $this->serviceinfo_uid;
return $this->serviceinfo_uid === null ? null : (int) $this->serviceinfo_uid;
}
final public function getServerInfoUid(): ?int
{
return $this->serverinfo_uid;
return $this->serverinfo_uid === null ? null : (int) $this->serverinfo_uid;
}
public function getCode(): string
{

View File

@ -9,22 +9,7 @@ class PaymentEntity extends CommonEntity
{
const PK = PaymentModel::PK;
const TITLE = PaymentModel::TITLE;
protected array $nullableFields = [
'serviceinfo_uid',
'serverpartinfo_uid',
];
protected $attributes = [
'serviceinfo_uid' => null,
'serverpartinfo_uid' => null,
'title' => '',
'amount' => 0,
'billing' => "",
'billing_at' => "",
'billing_month' => 0,
'pay' => "",
'status' => '',
'content' => ''
];
public function __construct(array|null $data = null)
{
parent::__construct($data);
@ -39,19 +24,19 @@ class PaymentEntity extends CommonEntity
}
public function getUserUid(): ?int
{
return $this->user_uid;
return $this->user_uid === null ? null : (int) $this->user_uid;
}
public function getClientInfoUid(): ?int
{
return $this->clientinfo_uid;
return $this->clientinfo_uid === null ? null : (int) $this->clientinfo_uid;
}
public function getServiceInfoUid(): ?int
{
return $this->serviceinfo_uid;
return $this->serviceinfo_uid === null ? null : (int) $this->serviceinfo_uid;
}
public function getServerPartInfoUid(): ?int
{
return $this->serverpartinfo_uid;
return $this->serverpartinfo_uid === null ? null : (int) $this->serverpartinfo_uid;
}
//기본기능
public function getCustomTitle(): string

View File

@ -28,6 +28,7 @@ abstract class CommonForm
private array $_batchjobButtons = ['batchjob' => '일괄처리', 'batchjob_delete' => '일괄삭제'];
protected $formAction = null;
protected $isDebug = false;
protected function __construct()
{
@ -239,94 +240,78 @@ abstract class CommonForm
* 데이터를 검증하고 유효하지 않을 경우 예외를 발생시킵니다.
* 2025 CI4 표준: 규칙 배열 내에 label을 포함하여 한글 메시지 출력을 보장합니다.
*/
public function validate_process(array &$formDatas, $isDebug = false): array
{
// 1) 전체 라벨/룰
$allFormFields = $this->getFormFields(); // ['field' => '라벨', ...]
$allFormRules = $this->getFormRules(); // ['field' => 'rules', ...]
if (empty($allFormRules)) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: 지정된 Form RULE이 없습니다.");
}
if ($this->formAction === 'modify') {
// (1) formDatas에 실제로 넘어온 필드만
$targetFields = array_keys($formDatas);
if ($isDebug) {
log_message('debug', static::class . '->' . __FUNCTION__ . "에서 Validate targetFields Begin DEBUG");
log_message('debug', var_export($targetFields, true));
}
// // (2) 내부 제어용 키 제거(프로젝트에 맞게 추가/삭제)
// $exclude = ['_method', 'csrf_test_name', 'submit', 'token', 'action'];
// $targetFields = array_values(array_diff($targetFields, $exclude));
// // (3) wildcard(role.*) 같은 규칙이 있으면 부모 기반으로 같이 포함
// // - formDatas에 role이 있으면 role.* 규칙도 함께 검사되도록 추가
// foreach ($allFormRules as $ruleField => $_ruleStr) {
// $ruleField = (string) $ruleField;
// if (!str_contains($ruleField, '.*')) {
// continue;
// }
// $parent = str_replace('.*', '', $ruleField);
// if (in_array($parent, $targetFields, true)) {
// $targetFields[] = $ruleField; // e.g. 'role.*'
// }
// }
// // (4) 실제로 룰이 정의된 필드만 남김
// $targetFields = array_values(array_intersect($targetFields, array_keys($allFormRules)));
if ($isDebug) {
log_message('debug', static::class . '->' . __FUNCTION__ . "에서 Validate targetFields End DEBUG");
log_message('debug', var_export($targetFields, true));
}
// 최종: modify에서는 "타겟만" 룰/라벨 세팅
$formFields = $this->getFormFields($targetFields);
$formRules = $this->getFormRules($targetFields);
// throw new RuntimeException(static::class . "->targetFields" . implode(",", $targetFields) . "\nformRules:" . implode(",", array_keys($formRules)) . "\nformFields:" . implode(",", array_keys($formFields)));
}//modify
// 2) 액션별 "검증 대상 필드" 결정
// $formFields = $allFormFields;
// $formRules = $allFormRules;
return array($formFields, $formRules, $allFormFields);
}
final public function validate(array &$formDatas, $isDebug = false): void
final public function validate(array &$formDatas): void
{
log_message('debug', '>>> CommonForm::validate CALLED: ' . static::class . ', formAction:' . $this->formAction);
try {
// 0) 데이터 구조 정리 (null 변환 X)
$formDatas = $this->sanitizeFormDatas($formDatas);
list($formFields, $formRules, $allFormFields) = $this->validate_process($formDatas, $isDebug);
if (empty($formRules)) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: 검증할 대상 RULE이 없습니다.");
// 1) 검증 대상 라벨/룰 결정
// 1) 전체 라벨/룰
$allFormFields = $this->getFormFields(); // ['field' => '라벨', ...]
$allFormRules = $this->getFormRules(); // ['field' => 'rules', ...]
if (empty($allFormRules)) {
throw new RuntimeException(
static::class . '->' . __FUNCTION__ . "에서 오류발생: 지정된 Form RULE이 없습니다."
);
}
// 3) wildcard(role.*) 부모 배열 보정
// modify/create 공통: 전체 룰 기준
$formFields = $allFormFields;
$formRules = $allFormRules;
if ($this->isDebug) {
log_message('debug', static::class . '->' . __FUNCTION__ . "에서 Validate ALL Begin DEBUG");
log_message('debug', 'formAction=' . (string) $this->formAction);
log_message('debug', 'formDatas keys=' . var_export(array_keys($formDatas), true));
log_message('debug', 'formRules keys=' . var_export(array_keys($formRules), true));
log_message('debug', static::class . '->' . __FUNCTION__ . "에서 Validate ALL End DEBUG");
}
if (empty($formRules)) {
throw new RuntimeException(
static::class . '->' . __FUNCTION__ . "에서 오류발생: 검증할 대상 RULE이 없습니다."
);
}
// 2) wildcard(role.*) 부모 배열 보정
$this->ensureParentArrayForWildcardRules($formDatas, $formRules);
// 5) dynamicRules 구성
// 3) dynamicRules 구성
$dynamicRules = [];
foreach ($formRules as $field => $rule) {
[$fieldName, $ruleStr] = $this->getValidationRule((string) $field, (string) $rule);
// label 결정
if (isset($formFields[$fieldName])) {
$label = $formFields[$fieldName];
} elseif (str_contains($fieldName, '.*')) {
$parentField = str_replace('.*', '', $fieldName);
$label = ($allFormFields[$parentField] ?? $formFields[$parentField] ?? $fieldName) . " 항목";
$label = ($allFormFields[$parentField] ?? $formFields[$parentField] ?? $fieldName) . ' 항목';
} else {
$label = $fieldName;
}
$dynamicRules[$fieldName] = [
'label' => $label,
'rules' => $ruleStr,
];
}
if ($isDebug) {
if ($this->isDebug) {
log_message('debug', static::class . '->' . __FUNCTION__ . "에서 Validate dynamicRules DEBUG");
log_message('debug', var_export($formDatas, true));
log_message('debug', var_export($dynamicRules, true));
log_message('debug', 'formDatas=' . var_export($formDatas, true));
log_message('debug', 'dynamicRules=' . var_export($dynamicRules, true));
}
$this->_validation->setRules($dynamicRules);
if (!$this->_validation->run($formDatas)) {
$errors = $this->_validation->getErrors();
throw new RuntimeException(sprintf(
"%s->%s작업 필수항목\nformDatas->%s\ndynamicRules->%s\n%s",
static::class,
@ -336,12 +321,14 @@ abstract class CommonForm
implode("\n", $errors)
));
}
} catch (\Throwable $e) {
if ($e instanceof RuntimeException) {
throw $e;
}
// throw new RuntimeException("유효성 검사 중 시스템 오류 발생: " . $e->getMessage());
throw new RuntimeException(
static::class . '->' . __FUNCTION__ . "에서 유효성 검사 중 시스템 오류 발생: " . $e->getMessage()
);
}
}

View File

@ -42,15 +42,16 @@ abstract class CommonService
return $result;
} catch (FormValidationException $e) {
// 검증 에러는 감싸지 말고 그대로 던져야 Ajax가 422 + errors 받음
// 검증 에러는 감싸지 말고 그대로 던져야 Ajax가 422 + errors 받음
$db->transRollback();
throw $e;
} catch (DatabaseException $e) {
$db->transRollback();
$errorMessage = sprintf(
"\n----[%s]에서 트랜잭션 실패: DB 오류----\n%s\n%s\n------------------------------\n",
static::class . '->' . ($functionName ?: 'dbTransaction'),
$this->model->getLastQuery() ?? "No Query Available",
$this->model->getLastQuery() ?? 'No Query Available',
$e->getMessage()
);
log_message('error', $errorMessage);
@ -58,7 +59,6 @@ abstract class CommonService
} catch (\Throwable $e) {
$db->transRollback();
// ✅ 여기서 FormValidationException까지 RuntimeException으로 바뀌던게 문제였음
throw new RuntimeException($e->getMessage(), $e->getCode(), $e);
}
}
@ -73,7 +73,7 @@ abstract class CommonService
'title_field' => $this->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
'class_path' => $this->getClassPaths(false)
'class_path' => $this->getClassPaths(false),
]);
}
}
@ -90,12 +90,13 @@ abstract class CommonService
'title_field' => $this->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
'class_path' => $this->getClassPaths(false)
'class_path' => $this->getClassPaths(false),
]);
}
}
return $this->_helper;
}
final public function getAuthContext(): AuthContext
{
if ($this->_authContext === null) {
@ -103,14 +104,17 @@ abstract class CommonService
}
return $this->_authContext;
}
final protected function addClassPaths(string $path): void
{
$this->_classPaths[] = $path;
}
final public function getPKField(): string
{
return $this->model->getPKField();
}
final public function getTitleField(): string
{
return $this->model->getTitleField();
@ -120,16 +124,19 @@ abstract class CommonService
{
return $isArray ? $this->_classPaths : implode($delimeter, $this->_classPaths);
}
final public function getNextPK(): int
{
$pkField = $this->getPKField();
$row = $this->model->selectMax($pkField)->get()->getRow();
return isset($row->{$pkField}) ? ((int) $row->{$pkField} + 1) : 1;
}
/**
* 단일 엔티티를 조회합니다.
*/
abstract protected function getEntity_process(CommonEntity $entity): CommonEntity;
abstract protected function getEntity_process($entity): CommonEntity;
final public function getEntity($where = null, ?string $message = null): ?CommonEntity
{
try {
@ -137,134 +144,163 @@ abstract class CommonService
if ($where !== null) {
$entity = is_array($where) ? $this->model->where($where)->first() : $this->model->find($where);
}
if ($entity === null) {
return null;
}
// 💡 동적으로 가져온 Entity 클래스 이름으로 instanceof 검사
$entityClass = $this->getEntityClass();
if (!$entity instanceof $entityClass) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생:Return Type은 {$entityClass}만 가능:" . get_class($entity));
throw new RuntimeException(
static::class . '->' . __FUNCTION__ . "에서 오류발생:Return Type은 {$entityClass}만 가능:" . get_class($entity)
);
}
return $this->getEntity_process($entity);
} catch (DatabaseException $e) {
$errorMessage = sprintf(
"\n------DB Query 오류 (%s)-----\nQuery: %s\nError: %s\n------------------------------\n",
static::class . '->' . __FUNCTION__,
$this->model->getLastQuery() ?? "No Query Available",
$this->model->getLastQuery() ?? 'No Query Available',
$e->getMessage()
);
log_message('error', $errorMessage);
throw new RuntimeException($errorMessage, $e->getCode(), $e);
} catch (\Exception $e) {
} catch (\Throwable $e) {
$errorMessage = sprintf(
"\n------일반 오류 (%s)-----\nError: %s\n------------------------------\n",
static::class . '->' . __FUNCTION__,
$e->getMessage()
);
throw new \Exception($errorMessage, $e->getCode(), $e);
throw new RuntimeException($errorMessage, $e->getCode(), $e);
}
}
/**
* 엔티티 배열 조회합니다.
* @return CommonEntity|null CommonEntity 인스턴스 또는 찾지 못했을 경우 null
* @return CommonEntity[] CommonEntity 인스턴스 배열
*/
protected function getEntities_process(mixed $where = null, array $columns = ['*'], array $entities = []): array
{
if ($where) {
$this->model->where($where);
}
//기본 Order By 이용하기위해
// 기본 Order By 이용
$this->setOrderBy();
if (!empty($columns) && $columns !== ['*']) {
$this->model->select(implode(',', $columns));
}
/** @var array<\App\Entities\CommonEntity> $results */
$results = $this->model->select(implode(',', $columns))->findAll();
log_message('debug', $this->model->getLastQuery());
$results = $this->model->findAll();
log_message('debug', (string) $this->model->getLastQuery());
foreach ($results as $entity) {
$entities[] = $entity;
}
return $entities;
}
public function getEntities(?array $where = null, array $columns = ['*'], array $entities = []): array
{
try {
/** @var array<\App\Entities\CommonEntity> $entities */
$entities = $this->getEntities_process($where, $columns, $entities);
return $entities;
} catch (DatabaseException $e) {
$errorMessage = sprintf(
"\n------DB Query 오류 (%s)-----\nQuery: %s\nError: %s\n------------------------------\n",
static::class . '->' . __FUNCTION__,
$this->model->getLastQuery() ?? "No Query Available",
$this->model->getLastQuery() ?? 'No Query Available',
$e->getMessage()
);
log_message('error', $errorMessage);
throw new RuntimeException($errorMessage, $e->getCode(), $e);
} catch (\Exception $e) {
} catch (\Throwable $e) {
$errorMessage = sprintf(
"\n------일반 오류 (%s)-----\nError: %s\n------------------------------\n",
static::class . '->' . __FUNCTION__,
$e->getMessage()
);
throw new \Exception($errorMessage, $e->getCode(), $e);
throw new RuntimeException($errorMessage, $e->getCode(), $e);
}
}
//CURD 결과처리용
protected function save_process(CommonEntity $entity): CommonEntity
// CURD 결과처리용
protected function save_process($entity): CommonEntity
{
try {
if (!$this->model->save($entity)) {
$errors = $this->model->errors();
$errorMsg = is_array($errors) ? implode(", ", $errors) : "DB 저장 작업이 실패했습니다.";
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: " . $errorMsg);
$errorMsg = is_array($errors) ? implode(', ', $errors) : 'DB 저장 작업이 실패했습니다.';
throw new RuntimeException(static::class . '->' . __FUNCTION__ . '에서 오류발생: ' . $errorMsg);
}
return $entity;
} catch (\Throwable $e) {
log_message('debug', __FUNCTION__ . ":" . var_export($entity, true));
log_message('debug', __FUNCTION__ . ":" . $this->model->getLastQuery());
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생:" . $e->getMessage());
log_message('debug', __FUNCTION__ . ':' . var_export($entity, true));
log_message('debug', __FUNCTION__ . ':' . (string) $this->model->getLastQuery());
throw new RuntimeException(static::class . '->' . __FUNCTION__ . '에서 오류발생:' . $e->getMessage());
}
}
//Action 작업시 field에따른 Hook처리(각 Service에서 override);
// Action 작업시 field에따른 Hook처리(각 Service에서 override)
protected function fieldhook_process(string $field, $value, array $formDatas): array
{
return $formDatas;
}
// 생성용
protected function create_process_validate(CommonForm &$actionForm, array $formDatas)
{
$actionForm->validate($formDatas); // ✅ 여기서 검증
}
protected function create_process(array $formDatas): CommonEntity
{
try {
$actionForm = $this->getActionForm();
if (!$actionForm instanceof CommonForm) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: actionForm이 정의되지 않았습니다.");
throw new RuntimeException(static::class . '->' . __FUNCTION__ . '에서 오류발생: actionForm이 정의되지 않았습니다.');
}
// create 폼 초기화
$actionForm->form_init_process('create', $formDatas);
$this->create_process_validate($actionForm, $formDatas);
// 검증 통과 후 엔티티 반영용
foreach ($formDatas as $field => $value) {
$formDatas = $this->fieldhook_process($field, $value, $formDatas);
// 검증
$actionForm->validate($formDatas);
// 후처리
$processedDatas = $formDatas;
foreach (array_keys($processedDatas) as $field) {
$value = $processedDatas[$field] ?? null;
$processedDatas = $this->fieldhook_process($field, $value, $processedDatas);
}
$entityClass = $this->getEntityClass();
$entity = new $entityClass($formDatas);
$entity = new $entityClass($processedDatas);
if (!$entity instanceof CommonEntity) {
throw new RuntimeException('Return Type은 CommonEntity만 가능');
}
if (!$entity instanceof $entityClass) {
throw new RuntimeException("Return Type은 {$entityClass}만 가능");
}
$entity->fill($formDatas);
$entity = $this->save_process($entity);
// 생성 PK 설정
if ($this->model->useAutoIncrement()) {
$entity->{$this->getPKField()} = $this->model->getInsertID();
}
return $entity;
} catch (FormValidationException $e) {
throw $e; // ✅ 감싸지 말고 그대로
throw $e;
} catch (\Throwable $e) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생:" . $e->getMessage());
throw new RuntimeException(static::class . '->' . __FUNCTION__ . '에서 오류발생:' . $e->getMessage());
}
}
@ -277,36 +313,48 @@ abstract class CommonService
}
// 수정용
protected function modify_process_validate(CommonForm &$actionForm, array $formDatas)
{
$actionForm->validate($formDatas); // ✅ 여기서 검증
}
protected function modify_process($entity, array $formDatas): CommonEntity
{
try {
$actionForm = $this->getActionForm();
if (!$actionForm instanceof CommonForm) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: actionForm이 정의되지 않았습니다.");
}
$actionForm->form_init_process('modify', $formDatas);
$this->modify_process_validate($actionForm, $formDatas);
// 검증 통과 후 엔티티 반영
foreach ($formDatas as $field => $value) {
$formDatas = $this->fieldhook_process($field, $value, $formDatas);
}
$entity->fill($formDatas);
if (!$entity->hasChanged()) {
return $entity;
}
$entity = $this->save_process($entity);
return $entity;
} catch (FormValidationException $e) {
throw $e; // ✅ 감싸지 말고 그대로
} catch (\Throwable $e) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생:" . $e->getMessage());
}
throw new RuntimeException(
static::class . '->' . __FUNCTION__ . '에서 오류발생: actionForm이 정의되지 않았습니다.'
);
}
// 기존 엔티티 데이터 + 수정 데이터 병합
$validateFormDatas = $entity->toArray();
foreach ($formDatas as $key => $value) {
$validateFormDatas[$key] = $value;
}
// 병합 데이터 기준으로 modify 폼 초기화
$actionForm->form_init_process('modify', $validateFormDatas);
// 검증
$actionForm->validate($validateFormDatas);
// 후처리
$processedDatas = $validateFormDatas;
foreach (array_keys($processedDatas) as $field) {
$value = $processedDatas[$field] ?? null;
$processedDatas = $this->fieldhook_process($field, $value, $processedDatas);
}
$entity->fill($processedDatas);
if ($entity->hasChanged()) {
$entity = $this->save_process($entity);
}
return $entity;
} catch (FormValidationException $e) {
throw $e;
} catch (\Throwable $e) {
throw new RuntimeException(
static::class . '->' . __FUNCTION__ . '에서 오류발생:' . $e->getMessage()
);
}
}
final public function modify(string|int $uid, array $formDatas): CommonEntity
{
@ -315,6 +363,7 @@ abstract class CommonService
if (!$entity) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: {$uid}에 해당하는 정보을 찾을수 없습니다.");
}
$formDatas['user_uid'] = (int) $this->getAuthContext()->getUID();
return $this->modify_process($entity, $formDatas);
}, __FUNCTION__);
@ -326,22 +375,27 @@ abstract class CommonService
$entity = $this->modify_process($entity, $formDatas);
return $entity;
}
final public function batchjob(array $uids, array $formDatas): array
{
return $this->dbTransaction(function () use ($uids, $formDatas) {
$entities = [];
foreach ($uids as $uid) {
$entity = $this->getEntity($uid);
if (!$entity) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: {$uid}에 해당하는 정보을 찾을수 없습니다.");
}
$entityClass = $this->getEntityClass();
if (!$entity instanceof $entityClass) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생:Return Type은 {$entityClass}만 가능");
}
$formDatas['user_uid'] = $this->getAuthContext()->getUID();
$formDatas['user_uid'] = (int) $this->getAuthContext()->getUID();
$entities[] = $this->batchjob_process($entity, $formDatas);
}
return $entities;
}, __FUNCTION__);
}
@ -350,28 +404,32 @@ abstract class CommonService
protected function delete_process($entity): CommonEntity
{
$result = $this->model->delete($entity->getPK());
log_message('debug', $this->model->getLastQuery());
if ($result === false) {
$errors = $this->model->errors();
$errorMsg = is_array($errors) ? implode(", ", $errors) : "삭제 작업이 실패했습니다.";
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: " . $errorMsg);
$errorMsg = is_array($errors) ? implode(', ', $errors) : '삭제 작업이 실패했습니다.';
throw new RuntimeException(static::class . '->' . __FUNCTION__ . '에서 오류발생: ' . $errorMsg);
}
return $entity;
}
final public function delete(string|int $uid): CommonEntity
{
return $this->dbTransaction(function () use ($uid) {
if (!$uid) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 삭제에 필요한 PrimaryKey 가 정의 되지 않았습니다.");
throw new RuntimeException(static::class . '->' . __FUNCTION__ . '에서 삭제에 필요한 PrimaryKey 가 정의 되지 않았습니다.');
}
$entity = $this->getEntity($uid);
if (!$entity) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: {$uid}에 해당하는 정보을 찾을수 없습니다.");
}
$entityClass = $this->getEntityClass();
if (!$entity instanceof $entityClass) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생:Return Type은 {$entityClass}만 가능");
}
return $this->delete_process($entity);
}, __FUNCTION__);
}
@ -387,17 +445,21 @@ abstract class CommonService
{
return $this->dbTransaction(function () use ($uids) {
$entities = [];
foreach ($uids as $uid) {
$entity = $this->getEntity($uid);
if (!$entity) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: {$uid}에 해당하는 정보을 찾을수 없습니다.");
}
$entityClass = $this->getEntityClass();
if (!$entity instanceof $entityClass) {
throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생:Return Type은 {$entityClass}만 가능");
}
$entities[] = $this->batchjob_delete_process($entity);
}
return $entities;
}, __FUNCTION__);
}
@ -407,16 +469,19 @@ abstract class CommonService
{
return $this->model->countAllResults();
}
// Limit처리
final public function setLimit(int $perpage): void
{
$this->model->limit($perpage);
}
// Offset처리
final public function setOffset(int $offset): void
{
$this->model->offset($offset);
}
public function setFilter(string $field, mixed $filter_value): void
{
switch ($field) {
@ -425,24 +490,27 @@ abstract class CommonService
break;
}
}
// 검색어조건절처리
public function setSearchWord(string $word): void
{
$this->model->orLike($this->model->getTable() . "." . $this->getTitleField(), $word, 'both');
$this->model->orLike($this->model->getTable() . '.' . $this->getTitleField(), $word, 'both');
}
//날자검색
// 날짜검색
public function setDateFilter(string $start, string $end): void
{
$this->model->where(sprintf("%s.created_at >= '%s 00:00:00'", $this->model->getTable(), $start));
$this->model->where(sprintf("%s.created_at <= '%s 23:59:59'", $this->model->getTable(), $end));
$this->model->where("{$this->model->getTable()}.created_at >=", $start . ' 00:00:00');
$this->model->where("{$this->model->getTable()}.created_at <=", $end . ' 23:59:59');
}
// OrderBy 처리
public function setOrderBy(mixed $field = null, mixed $value = null): void
{
if ($field !== null && $value !== null) {
$this->model->orderBy(sprintf("%s.%s %s", $this->model->getTable(), $field, $value));
$this->model->orderBy($this->model->getTable() . '.' . $field, (string) $value);
} else {
$this->model->orderBy(sprintf("%s.%s %s", $this->model->getTable(), $this->getPKField(), "DESC"));
$this->model->orderBy($this->model->getTable() . '.' . $this->getPKField(), 'DESC');
}
}
}

View File

@ -4,7 +4,6 @@ namespace App\Services\Customer;
use App\Entities\CommonEntity;
use App\Entities\Customer\ServiceEntity;
use App\Forms\CommonForm;
use App\Forms\Customer\ServiceForm;
use App\Helpers\Customer\ServiceHelper;
use App\Models\Customer\ServiceModel;
@ -120,10 +119,6 @@ class ServiceService extends CustomerService
return $entity;
}
protected function modify_process_validate(CommonForm &$actionForm, array $formDatas)
{
$actionForm->validate($formDatas, true); // ✅ 여기서 검증
}
protected function modify_process($entity, array $formDatas): ServiceEntity
{
if (empty($formDatas['serverinfo_uid'])) {