trafficmonitor init...2

This commit is contained in:
choi.jh 2025-11-07 15:54:28 +09:00
parent c6219c0aab
commit 7621ea514b
13 changed files with 374 additions and 303 deletions

View File

@ -2,18 +2,15 @@
namespace App\Controllers\Auth;
use App\DTOs\Auth\GoogleDTO;
use App\Entities\UserEntity;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;
use App\Libraries\MySocket\GoogleSocket\API as GoogleSocket;
use App\Entities\UserEntity;
class GoogleController extends AuthController
{
public const PATH = 'login';
private ?GoogleSocket $_socket = null;
private $_service = null;
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
parent::initController($request, $response, $logger);
@ -27,15 +24,12 @@ class GoogleController extends AuthController
//구글 로그인 BUTTON용
$this->addViewDatas('SNSButton', anchor($this->service->socket->createAuthUrl(), ICONS['GOOGLE'] . 'Google 로그인', ["class" => "btn-google"]));
}
//로그인처리
protected function login_process(): UserEntity
{
$formDatas = $this->doValidation($this->getViewDatas('action'));
if (!array_key_exists('access_code', $formDatas) || !$formDatas['access_code']) {
throw new \Exception("구글 로그인 실패");
}
return $this->service->login($formDatas);
//요청 데이터를 DTO 객체로 변환
$dto = new GoogleDTO($this->request->getPost());
return $this->service->login($dto);
}
protected function logout_process(): void
{

View File

@ -27,7 +27,6 @@ class LocalController extends AuthController
//로그인처리
protected function login_process(): UserEntity
{
//요청 데이터를 DTO 객체로 변환
$dto = new LocalDTO($this->request->getPost());
return $this->service->login($dto);
}

View File

@ -23,14 +23,11 @@ abstract class CommonController extends BaseController
private array $_action_paths = [];
private array $_viewDatas = [];
protected $service = null;
protected $authService = null;
protected $myCertification = null;
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
parent::initController($request, $response, $logger);
//로그인관련
$this->authService = service('myauth');
$this->myCertification = CertificationDTO::fromByAuthService($this->authService);
$this->myCertification = CertificationDTO::byAuthContext(service('myauth')->getAuthContext());
}
protected function getLayout(): string
{

View File

@ -2,7 +2,7 @@
namespace App\DTOs;
use App\Services\Auth\AuthService;
use App\Libraries\AuthContext;
use CodeIgniter\Entity\Entity; // DTO가 Entity를 상속받지 않는 경우, 필요한 경우 CommonDTO 또는 Entity 상속을 유지합니다.
class CertificationDTO extends Entity // DTO가 Entity를 상속받는 것으로 가정합니다.
@ -22,15 +22,15 @@ class CertificationDTO extends Entity // DTO가 Entity를 상속받는 것으로
}
}
}
public static function fromByAuthService(AuthService $service): self
//인증 정보
public static function byAuthContext(AuthContext $authContext): self
{
return new self(
[
'isLogin' => $service->isLoggedIn(),
'uid' => $service->getUID(),
'name' => $service->getName(),
'role' => $service->getRole(), //배열(array|null)을 반환합니다.
'isLogin' => $authContext->isLoggedIn(),
'uid' => $authContext->getUID(),
'name' => $authContext->getName(),
'role' => $authContext->getRole(), //배열(array|null)을 반환합니다.
]
);
}

View File

@ -26,20 +26,20 @@ class AuthFilter implements FilterInterface
*/
public function before(RequestInterface $request, $arguments = null)
{
$auth = service('myauth');
$authContext = service('myauth')->getAuthContext();
// var_dump($arguments);
// log_message("debug", var_export($arguments, true));
// exit;
// 로그인 않했으면
if (!$auth->isLoggedIn()) {
$auth->pushCurrentUrl($request->getUri()->getPath() . ($request->getUri()->getQuery() ? "?" . $request->getUri()->getQuery() : ""));
if (!$authContext->isLoggedIn()) {
$authContext->pushCurrentUrl($request->getUri()->getPath() . ($request->getUri()->getQuery() ? "?" . $request->getUri()->getQuery() : ""));
return redirect()->to(URLS['LOGIN'])->with('error', '로그인을하셔야합니다.');
}
//User Role 비교 // 회원 ROLES이 필요ROLE($arguments) 목록에 존재하지 않으면(ACL)
if (!$auth->isAccessRole($arguments)) {
if (!$authContext->isAccessRole($arguments)) {
return redirect()->back()->with(
'error',
"회원[{$auth->getName()}]님은 접속에 필요한 권한이 없습니다. "
"회원[{$authContext->getName()}]님은 접속에 필요한 권한이 없습니다. "
);
}
}

View File

@ -9,7 +9,6 @@ class TrafficHelper extends CommonHelper
public function __construct()
{
parent::__construct();
$this->setTitleField(TrafficModel::TITLE);
}
public function getFieldForm(string $field, mixed $value, array $viewDatas, array $extras = []): string
{

View File

@ -0,0 +1,137 @@
<?php
namespace App\Libraries;
use App\Entities\UserEntity;
use CodeIgniter\Session\Session;
/**
* AuthContext
* 인증 세션의 저장, 조회 파괴를 관리합니다.
* AuthService의 세션 로직을 분리하여 SRP를 준수합니다.
*/
class AuthContext
{
private Session $session;
private string $urlStackName = "url_stack";
// 환경 설정에서 정의된 상수라고 가정합니다.
const SESSION_IS_LOGIN = 'ISLOGIN';
const SESSION_AUTH_INFO = 'AUTH';
public function __construct()
{
// 세션 서비스를 직접 사용합니다.
$this->session = \Config\Services::session();
}
private function getAuthInfo(string $key = ""): array|string|null
{
$authInfo = $this->session->get(self::SESSION_AUTH_INFO);
if ($key) {
return $authInfo[$key] ?? null;
}
return $authInfo;
}
// ----------------------------------------------------
// Public Accessors (AuthService에서 이동)
// ----------------------------------------------------
public function getUID(): string|null
{
return $this->getAuthInfo('uid');
}
public function getID(): string|null
{
return $this->getAuthInfo('id');
}
public function getName(): string|null
{
return $this->getAuthInfo('name');
}
public function getRole(): array|null
{
return $this->getAuthInfo('role');
}
public function isLoggedIn(): bool
{
return $this->session->has(self::SESSION_IS_LOGIN);
}
public function isAccessRole(array $roles): bool
{
$userRoles = $this->getRole();
if (empty($userRoles) || !is_array($userRoles)) {
return false;
}
return !empty(array_intersect($userRoles, $roles));
}
public function pushCurrentUrl(string $url): void
{
$this->session->set($this->urlStackName, $url);
}
public function popPreviousUrl(): string
{
$url = $this->session->get($this->urlStackName) ?? "";
if (!empty($url)) {
$this->session->set($this->urlStackName, ""); // 세션에서 제거
return $url;
}
return '/';
}
// ----------------------------------------------------
// Session Writers (Login/Logout Process)
// ----------------------------------------------------
/**
* 인증 성공 세션에 사용자 정보를 기록합니다.
*/
public function setAuthSession(UserEntity $entity): void
{
$this->session->set(self::SESSION_IS_LOGIN, true);
$this->session->set(self::SESSION_AUTH_INFO, [
'uid' => $entity->getPK(),
'id' => $entity->getID(),
'name' => $entity->getTitle(),
'role' => $entity->getRole()
]);
}
/**
* 로그아웃 세션 쿠키를 파괴합니다.
*/
public function destroyAuthSession(): void
{
// 세션 데이터 삭제
$this->session->remove(self::SESSION_IS_LOGIN);
$this->session->remove(self::SESSION_AUTH_INFO);
// 모든 세션 데이터 삭제
$this->session->destroy();
// 세션 쿠키 삭제 (AuthService에서 가져온 로직)
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(
session_name(),
'',
time() - 42000,
$params["path"],
$params["domain"],
$params["secure"],
$params["httponly"]
);
}
// 세션 재생성
session_start();
$this->session->regenerate(true);
}
}

View File

@ -9,7 +9,7 @@ class TrafficModel extends CommonModel
{
const TABLE = "trafficinfo";
const PK = "uid";
const TITLE = "title";
const TITLE = "switch";
protected $table = self::TABLE;
// protected $useAutoIncrement = false;
protected $primaryKey = self::PK;
@ -17,21 +17,10 @@ class TrafficModel extends CommonModel
protected $allowedFields = [
"uid",
"user_uid",
"clientinfo_uid",
"serverinfo_uid",
"payment_uid",
"code",
"title",
"site",
"location",
"rack",
"line",
"billing_at",
"sale",
"amount",
"start_at",
"end_at",
"history",
"switch",
"index",
"in",
"out",
"status",
"updated_at"
];
@ -39,11 +28,4 @@ class TrafficModel extends CommonModel
{
parent::__construct();
}
public function getFormRule(string $action, string $field): string
//입력전 코드처리
final public function create(array $formDatas): ServiceEntity
{
$formDatas['code'] = $formDatas['site'] . "_s" . uniqid();
return parent::create($formDatas);
}
}

View File

@ -5,148 +5,117 @@ namespace App\Services\Auth;
use App\Entities\UserEntity;
use App\Helpers\AuthHelper;
use App\Models\CommonModel;
use App\Services\CommonService;
use CodeIgniter\Session\Session;
use App\Libraries\AuthContext;
use CodeIgniter\Validation\Exceptions\ValidationException;
// 참고:https://github.com/SyntaxPhoenix/iloclient
abstract class AuthService extends CommonService
/**
* AuthService
* 인증(로그인) 워크플로우를 정의하는 템플릿 클래스입니다.
* CommonService를 상속받지 않아 불필요한 CRUD 구현을 요구하지 않습니다.
*/
abstract class AuthService
{
private ?Session $_session = null;
private $url_stack_name = "url_stack";
private ?AuthContext $_authContext = null;
private array $_classPaths = [];
protected $formServiceInstance = null;
protected ?CommonModel $model = null;
protected ?AuthHelper $helperInstance = null;
protected function __construct(CommonModel $model)
{
parent::__construct($model);
$this->model = $model; // 모델을 직접 주입받아 자식에게 전달
$this->addClassPaths('Auth');
}
abstract public function login(mixed $dto): UserEntity;
abstract public function getFormService(): mixed;
final public function getHelper(): AuthHelper
{
if ($this->helperInstance === null) {
$this->helperInstance = new AuthHelper();
// AuthHelper에 필요한 기본 메타데이터만 설정합니다. (CRUD 제거)
$this->helperInstance->setAttributes([
'pk_field' => $this->model->getPKField(),
'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
'class_path' => $this->getClassPaths(false)
'class_path' => $this->getClassPaths(false)
]);
}
return $this->helperInstance;
}
//Index,FieldForm관련
final public function getSession(): Session
//인증세션용
final public function getAuthContext(): AuthContext
{
if ($this->_session === null) {
$this->_session = \Config\Services::session();
if ($this->_authContext === null) {
$this->_authContext = new AuthContext();
}
return $this->_session;
return $this->_authContext;
}
private function getAuthInfo(string $key = ""): array|string|null
final protected function addClassPaths(string $path): void
{
$authInfo = $this->getSession()->get(SESSION_NAMES['AUTH']);
if ($key) {
return $authInfo[$key] ?? null;
}
return $authInfo;
$this->_classPaths[] = $path;
}
public function getFormFields(): array
final public function getClassPaths($isArray = true, $delimeter = DIRECTORY_SEPARATOR): array|string
{
return ['id', 'passwd'];
return $isArray ? $this->_classPaths : implode($delimeter, $this->_classPaths);
}
final public function getUID(): string|null
protected function getEntity_process(mixed $entity): mixed
{
return $this->getAuthInfo('uid');
}
final public function getID(): string|null
{
return $this->getAuthInfo('id');
}
final public function getName(): string|null
{
return $this->getAuthInfo('name');
}
/**
* 현재 로그인된 사용자의 역할을 배열 형태로 반환합니다.
* UserEntity::getRole() 반환 타입과 일치시킵니다.
* @return array|null
*/
final public function getRole(): array|null // <-- 타입 힌트를 array|null로 변경
{
// getAuthInfo는 UserEntity에서 배열을 받아옵니다.
return $this->getAuthInfo('role');
}
final public function isLoggedIn(): bool
{
return $this->getSession()->has(SESSION_NAMES['ISLOGIN']);
}
/**
* 사용자가 필요한 접근 권한($roles) 가지고 있는지 확인합니다.
* @param array $roles 요구되는 권한 목록
* @return bool
*/
final public function isAccessRole(array $roles): bool
{
// (1) getRole()의 반환 타입이 이제 배열이므로 바로 받습니다.
$userRoles = $this->getRole();
// 역할 정보 자체가 없거나 빈 배열인 경우 접근 불가
if (empty($userRoles) || !is_array($userRoles)) {
return false;
}
// (2) 문자열 explode() 대신 array_intersect를 사용하여 배열 간의 공통점을 찾습니다.
// 교집합이 없으면 false
return !empty(array_intersect($userRoles, $roles));
}
final public function pushCurrentUrl(string $url): void
{
$this->getSession()->set($this->url_stack_name, $url);
}
final public function popPreviousUrl(): string
{
$url = $this->getSession()->get($this->url_stack_name) ?? "";
if (!empty($url)) {
$this->pushCurrentUrl("");
return $url;
}
return '/'; // 기본 URL
}
final protected function login_process(UserEntity $entity): UserEntity
{
$this->getSession()->set(SESSION_NAMES['ISLOGIN'], true);
$this->getSession()->set(SESSION_NAMES['AUTH'], [
'uid' => $entity->getPK(),
'id' => $entity->getID(),
'name' => $entity->getTitle(),
'role' => $entity->getRole()
]);
return $entity;
}
final public function getEntity(string|int|array $where, ?string $message = null): mixed
{
try {
$entity = is_array($where) ? $this->model->where($where)->first() : $this->model->find($where);
if (!$entity) {
return null;
}
if (is_array($entity)) {
throw new \Exception(__METHOD__ . "에서 결과값 Array 오류발생:\n" . var_export($entity, true));
}
return $this->getEntity_process($entity);
} catch (\Exception $e) {
$message = sprintf(
"\n------%s SQL오류-----<BR>\n%s\n%s\n------------------------------\n",
__FUNCTION__,
$this->model->getLastQuery(),
$e->getMessage()
);
throw new \Exception($message);
}
}
final protected function getValidationRules(string $action, array $allRules = []): array
{
foreach ($this->getFormService()->getFormFields($action) as $field) {
$allRules = array_merge($allRules, $this->getValidationRule($action, $field, $allRules));
}
return $allRules;
}
protected function getValidationRule(string $action, string $field, array $rules = []): array
{
switch ($field) {
default:
$rules[$field] = $this->getFormService()->getValidationRule($action, $field);
break;
}
return $rules;
}
//로그인
abstract protected function login_process(array $formDatas): UserEntity;
public function login(object $dto): UserEntity
{
//입력값 검증
$formDatas = (array) $dto;
if (!service('validation')->setRules($this->getValidationRules(__FUNCTION__))->run($formDatas)) {
throw new ValidationException(implode("\n", service('validation')->getErrors()));
}
//인증처리
$entity = $this->login_process($formDatas);
//세션처리
$this->getAuthContext()->setAuthSession($entity);
return $entity;
}
//로그아웃
final public function logout(): void
{
// 세션 데이터 삭제
$this->getSession()->remove(SESSION_NAMES['ISLOGIN']);
$this->getSession()->remove(SESSION_NAMES['AUTH']);
// 모든 세션 데이터 삭제
$this->getSession()->destroy();
// 세션 쿠키 삭제
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(
session_name(),
'',
time() - 42000,
$params["path"],
$params["domain"],
$params["secure"],
$params["httponly"]
);
}
// 세션 재생성
session_start();
$this->getSession()->regenerate(true);
$this->getAuthContext()->destroyAuthSession();
}
}

View File

@ -33,39 +33,18 @@ class GoogleService extends AuthService
}
return $this->formServiceInstance;
}
public function getFormFields(): array
{
return ["access_code"];
}
public function getFormFilters(): array
{
return ["access_code"];
}
public function getBatchjobButtons(): array
{
return [];
}
//기본기능
public function login(mixed $dto): UserEntity
protected function login_process(array $formDatas): UserEntity
{
try {
if (!$dto instanceof GoogleDTO) {
throw new RuntimeException(__METHOD__ . "에서 오류발생: GoogleDTO만 사용하실수 있습니다");
}
// DTO 객체를 배열로 변환하여 검증기에 전달
$formDatas = (array) $dto;
if (!service('validation')->setRules($this->getFormRules(__FUNCTION__))->run($formDatas)) {
// 검증 실패 시, ValidationException을 던집니다.
throw new ValidationException(service('validation')->getErrors());
}
$this->socket->setToken($dto->access_code);
$this->socket->setToken($formDatas['access_code']);
$sns_entity = $this->socket->signup();
// local db 사용와의 연결 확인
$entity = $this->getEntity($sns_entity->getParent());
if (!$entity instanceof UserEntity) {
throw new PageNotFoundException("회원[{$sns_entity->getTitle()}]님은 아직 로컬사용자 연결이 이루어지지 않았습니다.");
}
return $this->login_process($entity);;
return $entity;
} catch (\Google_Service_Exception $e) {
log_message('error', '구글 서비스 예외발생: ' . $e->getMessage());
throw new PageNotFoundException("구글 로그인 중 오류가 발생했습니다. 다시 시도해 주세요.");
@ -74,4 +53,13 @@ class GoogleService extends AuthService
throw new PageNotFoundException("관리자에게 문의하시기 바랍니다.\n{$e->getMessage()}");
}
}
public function login(mixed $dto): UserEntity
{
if (!$dto instanceof GoogleDTO) {
throw new RuntimeException(__METHOD__ . "에서 오류발생: GoogleDTO만 사용하실수 있습니다");
}
return parent::login($dto);
// DTO 객체를 배열로 변환하여 검증기에 전달
$formDatas = (array) $dto;
}
}

View File

@ -6,7 +6,6 @@ use App\DTOs\Auth\LocalDTO;
use App\Entities\UserEntity;
use App\Forms\Auth\LocalForm;
use App\Models\UserModel;
use CodeIgniter\Validation\Exceptions\ValidationException;
use RuntimeException;
class LocalService extends AuthService
@ -16,6 +15,7 @@ class LocalService extends AuthService
parent::__construct($model);
$this->addClassPaths('Local');
}
public function getFormService(): LocalForm
{
if ($this->formServiceInstance === null) {
@ -25,42 +25,28 @@ class LocalService extends AuthService
'title_field' => $this->model->getTitleField(),
'table' => $this->model->getTable(),
'useAutoIncrement' => $this->model->useAutoIncrement(),
'class_path' => $this->getClassPaths(false)
'class_path' => $this->getClassPaths(false),
]);
}
return $this->formServiceInstance;
}
public function getFormFields(): array
protected function login_process(array $formDatas): UserEntity
{
return ["id", "passwd",];
}
public function getFormFilters(): array
{
return [];
}
public function getBatchjobButtons(): array
{
return [];
}
//기본기능
public function login(mixed $dto): UserEntity
{
if (!$dto instanceof LocalDTO) {
throw new RuntimeException(__METHOD__ . "에서 오류발생: LcoalDTO만 사용하실수 있습니다");
}
// DTO 객체를 배열로 변환하여 검증기에 전달
$formDatas = (array) $dto;
if (!service('validation')->setRules($this->getFormRules(__FUNCTION__))->run($formDatas)) {
// 검증 실패 시, ValidationException을 던집니다.
throw new ValidationException(implode("\n", service('validation')->getErrors()));
}
$entity = $this->getEntity(['id' => $dto->id, 'status' => STATUS['AVAILABLE']], false);
$entity = $this->getEntity(['id' => $formDatas['id'], 'status' => 'AVAILABLE'], true);
if (!$entity instanceof UserEntity) {
throw new \Exception("{$dto->id}에 대한 로그인 정보를 찾을수 없습니다.");
throw new \Exception("{$formDatas['id']}에 대한 로그인 정보를 찾을수 없습니다.");
}
if (!password_verify($dto->passwd, $entity->getPassword())) {
if (!password_verify($formDatas['passwd'], $entity->getPassword())) {
throw new \Exception("암호가 맞지 않습니다.");
}
return $this->login_process($entity);
return $entity;
}
public function login(object $dto): UserEntity
{
if (!$dto instanceof LocalDTO) {
throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다.");
}
return parent::login($dto);
}
}

View File

@ -2,7 +2,10 @@
namespace App\Services;
use App\Entities\CommonEntity;
use App\Models\CommonModel;
use CodeIgniter\Validation\Exceptions\ValidationException;
use RuntimeException;
abstract class CommonService
{
@ -96,6 +99,62 @@ abstract class CommonService
}
return $rules;
}
//CURD 결과처리용
//DB 결과 처리 로직 통합 및 개선
protected function handle_save_result(mixed $result, $entity): CommonEntity
{
if (!$result) {
// static::class는 현재 호출된 자식 클래스 이름 반환
throw new RuntimeException(static::class . "에서 {$entity->getTitle()} 등록/수정 중 DB 오류가 발생하였습니다.");
}
// 2. 최종 PK 값 결정 (insert/update 공통)
$pkValue = $this->model->useAutoIncrement() && is_numeric($result) && (int)$result > 0
? (int)$result
: $entity->{$this->model->primaryKey};
if (empty($pkValue)) {
throw new RuntimeException("{$entity->getTitle()} 저장 후 Primary Key를 확인할 수 없습니다.");
}
// 3. Entity 재조회 (수정 및 생성 모두 최신 DB 상태 반영)
$savedEntity = $this->model->find($pkValue);
if (!$savedEntity) {
throw new RuntimeException("등록/수정된 데이터를 찾을 수 없습니다. (PK: {$pkValue})");
}
return $savedEntity;
}
//생성용
abstract protected function create_process(array $formDatas): CommonEntity;
public function create(object $dto): CommonEntity
{
$formDatas = (array) $dto;
if (!service('validation')->setRules($this->getValidationRules(__FUNCTION__))->run($formDatas)) {
throw new ValidationException(implode("\n", service('validation')->getErrors()));
}
$entity = $this->create_process($formDatas);
$result = $this->model->insert($entity, $this->model->useAutoIncrement());
return $this->handle_save_result($result, $entity);
}
//수정용
abstract protected function modify_process(array $formDatas): array;
public function modify(object $dto): CommonEntity
{
$formDatas = (array) $dto;
if (!service('validation')->setRules($this->getValidationRules(__FUNCTION__))->run($formDatas)) {
throw new ValidationException(implode("\n", service('validation')->getErrors()));
}
list($pk, $updateData) = $this->modify_process($formDatas);
$entity = new ($this->model->returnType)($updateData); // 재조회에 필요한 PK를 얻기 위함
$result = $this->model->update($pk, $updateData);
return $this->handle_save_result($result, $entity);
}
protected function delete_process($uid): bool
{
return $this->model->delete($uid);
}
final public function delete($uid): bool
{
return $this->delete_process($uid);
}
//Index용
final public function getTotalCount(): int
{

View File

@ -3,6 +3,7 @@
namespace App\Services;
use App\DTOs\UserDTO;
use App\Entities\CommonEntity;
use App\Entities\UserEntity;
use App\Forms\UserForm;
use App\Helpers\UserHelper;
@ -46,93 +47,53 @@ class UserService extends CommonService
return $this->helperInstance;
}
//기본 기능부분
public function create(UserDTO $dto): UserEntity
protected function create_process(array $formDatas): UserEntity
{
// DTO 객체를 배열로 변환하여 검증기에 전달
$formDatas = (array) $dto;
// dd($formDatas);
if (!service('validation')->setRules($this->getValidationRules(__FUNCTION__))->run($formDatas)) {
throw new ValidationException(implode("\n", service('validation')->getErrors()));
}
$entity = new UserEntity($formDatas);
$result = $this->model->insert($entity);
if (!$result) {
throw new \Exception("{$entity->getTitle()} 등록 중 DB 오류가 발생하였습니다.");
}
// 💡 PK 타입에 따른 최종 Entity 반환 로직 분기
if ($this->model->useAutoIncrement) { //정수 PK인 경우
$savedEntity = $this->model->find($result);
} else { //문자열 PK인 경우
$pkValue = $entity->{$this->model->primaryKey};
$savedEntity = $this->model->find($pkValue);
}
if (!$savedEntity instanceof UserEntity) {
throw new \Exception("등록된 데이터를 찾을 수 없습니다.");
}
return $savedEntity;
return new UserEntity($formDatas);
}
public function modify(UserDTO $dto): UserEntity
public function create(object $dto): UserEntity
{
// DTO 객체를 배열로 변환하여 검증기에 전달
$formDatas = (array) $dto;
// dd($formDatas);
if (!service('validation')->setRules($this->getValidationRules(__FUNCTION__))->run($formDatas)) {
throw new ValidationException(implode("\n", service('validation')->getErrors()));
if (!$dto instanceof UserDTO) {
throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다.");
}
$entity = new UserEntity($formDatas);
$result = $this->model->update($entity->getPK(), $formDatas);
if (!$result) {
throw new \Exception("{$entity->getTitle()} 등록 중 DB 오류가 발생하였습니다.");
}
// 💡 PK 타입에 따른 최종 Entity 반환 로직 분기
if ($this->model->useAutoIncrement) { //정수 PK인 경우
$savedEntity = $this->model->find($result);
} else { //문자열 PK인 경우
$pkValue = $entity->{$this->model->primaryKey};
$savedEntity = $this->model->find($pkValue);
}
if (!$savedEntity instanceof UserEntity) {
throw new \Exception("등록된 데이터를 찾을 수 없습니다.");
}
return $savedEntity;
return parent::create($dto);
}
protected function modify_process(array $formDatas): array
{
// DTO에 PK가 포함되어 있다고 가정. 필요 시 데이터 가공
return [
$formDatas[$this->model->primaryKey], // PK
$formDatas // Update Data
];
}
public function modify(object $dto): UserEntity
{
if (!$dto instanceof UserDTO) {
throw new RuntimeException(__METHOD__ . "에서 오류발생:" . get_class($dto) . "는 사용할수 없습니다.");
}
return parent::modify($dto);
}
//List 검색용
//FormFilter 조건절 처리
public function index_condition_filterField(string $field, mixed $filter_value): void
{
switch ($field) {
case 'role':
$where = "FIND_IN_SET(" . $this->model->escape($filter_value) . ", {$this->model->getTable()}.{$field}) > 0";
//FIND_IN_SET()은 MySQL 함수이므로 CodeIgniter가 이를 일반 컬럼명으로 착각하고 escape하게 되면 오류가 발생합니다. 따라서 ->where($sql, null, false)로 명시하여 escape를 꺼줘야 정상 작동
$this->model->where($where, null, false);
break;
default:
parent::index_condition_filterField($field, $filter_value);
break;
}
}
//검색어조건절처리
public function index_condition_filterWord(string $word): void
{
$this->model->orLike($this->model->getTable() . '.id', $word, 'both');
$this->model->orLike($this->model->getTable() . "." . $this->model->getTitleField(), $word, 'both');
$this->model->orLike($this->model->getTable() . '.email', $word, 'both');
parent::index_condition_filterWord($word);
}
// protected function modify_process(mixed $entity, array $formDatas): UserEntity
// {
// // die(var_export($formDatas, true));
// //암호를 입력하지 않았을시는 변경하기 않게 하기위함
// if (isset($formDatas['passwd']) && $formDatas['passwd'] == "") {
// unset($formDatas['passwd']);
// unset($formDatas['confirmpassword']);
// }
// //Role을 지정이 있을경우에만 , toggle이나 batcjhjob에서는 없을수도 있으므로
// if (isset($formDatas['role'])) {
// $formDatas['role'] = implode(DEFAULTS["DELIMITER_ROLE"], $formDatas['role']);
// }
// // die(var_export($formDatas, true));
// $entity = parent::modify_process($entity, $formDatas);
// return $entity;
// }
// //List 검색용
// //FormFilter 조건절 처리
// public function index_condition_filterField(string $field, mixed $filter_value): void
// {
// switch ($field) {
// case 'role':
// $where = "FIND_IN_SET(" . $this->model->escape($filter_value) . ", {$this->model->getTable()}.{$field}) > 0";
// //FIND_IN_SET()은 MySQL 함수이므로 CodeIgniter가 이를 일반 컬럼명으로 착각하고 escape하게 되면 오류가 발생합니다. 따라서 ->where($sql, null, false)로 명시하여 escape를 꺼줘야 정상 작동
// $this->model->where($where, null, false);
// break;
// default:
// parent::index_condition_filterField($field, $filter_value);
// break;
// }
// }
// //검색어조건절처리
// public function index_condition_filterWord(string $word): void
// {
// $this->model->orLike($this->model->getTable() . '.id', $word, 'both');
// $this->model->orLike($this->model->getTable() . "." . $this->model->getTitleField(), $word, 'both');
// $this->model->orLike($this->model->getTable() . '.email', $word, 'both');
// parent::index_condition_filterWord($word);
// }
}