trafficmonitor init...2
This commit is contained in:
parent
65dff253d8
commit
c79db51fac
@ -384,3 +384,16 @@ define("STATUS", [
|
|||||||
'PAID' => 'paid',
|
'PAID' => 'paid',
|
||||||
'UNPAID' => 'unpaid',
|
'UNPAID' => 'unpaid',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
//ROLE
|
||||||
|
define("ROLE", [
|
||||||
|
'USER' => [
|
||||||
|
'MANAGER' => "manager",
|
||||||
|
'CLOUDFLARE' => "cloudflare",
|
||||||
|
'FIREWALL' => "firewall",
|
||||||
|
'SECURITY' => "security",
|
||||||
|
'DIRECTOR' => "director",
|
||||||
|
'MASTER' => "master",
|
||||||
|
],
|
||||||
|
['CLIENT'] => []
|
||||||
|
]);
|
||||||
|
|||||||
@ -37,10 +37,23 @@ class UserController extends AdminController
|
|||||||
return parent::getFormRule($action, $field, $rule);
|
return parent::getFormRule($action, $field, $rule);
|
||||||
}
|
}
|
||||||
//Index,FieldForm관련.
|
//Index,FieldForm관련.
|
||||||
protected function create_process(): UserEntity
|
protected function create_process(): RedirectResponse
|
||||||
{
|
{
|
||||||
//요청 데이터를 DTO 객체로 변환
|
//요청 데이터를 DTO 객체로 변환
|
||||||
$dto = new UserDTO($this->request->getPost());
|
$dto = new UserDTO($this->request->getPost());
|
||||||
return $this->service->create($dto);
|
$entity = $this->service->create($dto);
|
||||||
|
$redirect_url = $this->authService->popPreviousUrl() ?? implode(DIRECTORY_SEPARATOR, $this->getActionPaths());
|
||||||
|
return redirect()->to($redirect_url)->with('success', "{$entity->getTitle()} 계정 생성이 완료되었습니다.");
|
||||||
|
}
|
||||||
|
protected function modify_form_process($uid): UserEntity
|
||||||
|
{
|
||||||
|
if (!$uid) {
|
||||||
|
throw new \Exception("계정 번호가 정의 되지 않았습니다.");
|
||||||
|
}
|
||||||
|
$entity = $this->service->getEntity($uid);
|
||||||
|
if (!$entity instanceof UserEntity) {
|
||||||
|
throw new \Exception("{$uid}에 해당하는 계정을 찾을수 없습니다.");
|
||||||
|
}
|
||||||
|
return $entity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -117,7 +117,7 @@ abstract class CommonController extends BaseController
|
|||||||
return view($full_path, ['viewDatas' => $view_datas]);
|
return view($full_path, ['viewDatas' => $view_datas]);
|
||||||
}
|
}
|
||||||
protected function create_form_process(): void {}
|
protected function create_form_process(): void {}
|
||||||
final public function create_form(): string|RedirectResponse
|
final public function create_form(): string
|
||||||
{
|
{
|
||||||
$action = __FUNCTION__;
|
$action = __FUNCTION__;
|
||||||
try {
|
try {
|
||||||
@ -138,19 +138,14 @@ abstract class CommonController extends BaseController
|
|||||||
$this->getViewDatas()
|
$this->getViewDatas()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
protected function create_process(): mixed
|
abstract protected function create_process(): RedirectResponse;
|
||||||
{
|
|
||||||
return $this->service->create();
|
|
||||||
}
|
|
||||||
final public function create(): RedirectResponse
|
final public function create(): RedirectResponse
|
||||||
{
|
{
|
||||||
$action = __FUNCTION__;
|
$action = __FUNCTION__;
|
||||||
try {
|
try {
|
||||||
//초기화
|
//초기화
|
||||||
$this->action_init_process($action);
|
$this->action_init_process($action);
|
||||||
$this->create_process();
|
return $this->create_process();
|
||||||
$redirect_url = $this->authService->popPreviousUrl() ?? implode(DIRECTORY_SEPARATOR, $this->getActionPaths());
|
|
||||||
return redirect()->to($redirect_url)->with('success', static::class . "/{$action}이 완료되었습니다.");
|
|
||||||
} catch (ValidationException $e) {
|
} catch (ValidationException $e) {
|
||||||
// 검증 실패 시 폼으로 돌아가서 오류 메시지 표시
|
// 검증 실패 시 폼으로 돌아가서 오류 메시지 표시
|
||||||
log_message('error', $e->getMessage());
|
log_message('error', $e->getMessage());
|
||||||
@ -160,7 +155,29 @@ abstract class CommonController extends BaseController
|
|||||||
return redirect()->back()->withInput()->with('error', $e->getMessage());
|
return redirect()->back()->withInput()->with('error', $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
abstract protected function modify_form_process($uid): mixed;
|
||||||
|
final public function modify_form($uid): string
|
||||||
|
{
|
||||||
|
$action = __FUNCTION__;
|
||||||
|
try {
|
||||||
|
//초기화
|
||||||
|
$this->action_init_process($action);
|
||||||
|
$entity = $this->modify_form_process($uid);
|
||||||
|
$this->addViewDatas('entity', $entity);
|
||||||
|
$this->action_render_process($action);
|
||||||
|
// dd($this->getViewDatas());
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
log_message('error', $e->getMessage());
|
||||||
|
$this->addViewDatas(self::ACTION_RESULT, 'error');
|
||||||
|
$this->addViewDatas(self::ACTION_MESSAGE, $e->getMessage());
|
||||||
|
//오류발생시 리디렉션 대신 폼 뷰를 다시 렌더링하도록 action_view_process 호출
|
||||||
|
}
|
||||||
|
return $this->action_result_process(
|
||||||
|
$this->getActionPaths(),
|
||||||
|
$action,
|
||||||
|
$this->getViewDatas()
|
||||||
|
);
|
||||||
|
}
|
||||||
//리스트관련
|
//리스트관련
|
||||||
//조건절 처리
|
//조건절 처리
|
||||||
// protected function index_condition_process(): void
|
// protected function index_condition_process(): void
|
||||||
|
|||||||
@ -7,10 +7,11 @@ class UserDTO extends CommonDTO
|
|||||||
public ?int $uid = null;
|
public ?int $uid = null;
|
||||||
public ?string $id = null;
|
public ?string $id = null;
|
||||||
public ?string $passwd = null;
|
public ?string $passwd = null;
|
||||||
public ?string $passwd_confirm = null;
|
public ?string $confirmpassword = null;
|
||||||
|
public ?string $name = null;
|
||||||
public ?string $email = null;
|
public ?string $email = null;
|
||||||
public ?string $mobile = null;
|
public ?string $mobile = null;
|
||||||
public ?string $role = null;
|
public ?string $role = null;
|
||||||
public ?string $status = null;
|
public ?string $status = null;
|
||||||
|
|
||||||
public function __construct(array $datas = [])
|
public function __construct(array $datas = [])
|
||||||
@ -18,7 +19,12 @@ class UserDTO extends CommonDTO
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
foreach ($datas as $key => $value) {
|
foreach ($datas as $key => $value) {
|
||||||
if (property_exists($this, $key)) {
|
if (property_exists($this, $key)) {
|
||||||
$this->{$key} = $value;
|
if ($key === 'role' && is_array($value)) {
|
||||||
|
// 배열일 경우, 쉼표로 구분된 문자열로 변환하여 저장
|
||||||
|
$this->role = implode(DEFAULTS["DELIMITER_ROLE"], $value);
|
||||||
|
} else {
|
||||||
|
$this->{$key} = $value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,7 +34,8 @@ class UserDTO extends CommonDTO
|
|||||||
'uid' => $this->uid,
|
'uid' => $this->uid,
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'passwd' => $this->passwd,
|
'passwd' => $this->passwd,
|
||||||
'passwd_confirm' => $this->passwd_confirm,
|
'confirmpassword' => $this->confirmpassword,
|
||||||
|
'name' => $this->name,
|
||||||
'email' => $this->email,
|
'email' => $this->email,
|
||||||
'mobile' => $this->mobile,
|
'mobile' => $this->mobile,
|
||||||
'role' => $this->role,
|
'role' => $this->role,
|
||||||
|
|||||||
@ -9,18 +9,38 @@ class UserEntity extends CommonEntity
|
|||||||
{
|
{
|
||||||
const PK = Model::PK;
|
const PK = Model::PK;
|
||||||
const TITLE = Model::TITLE;
|
const TITLE = Model::TITLE;
|
||||||
const DEFAULT_STATUS = STATUS['AVAILABLE'];
|
const DEFAULT_STATUS = STATUS['AVAILABLE'];
|
||||||
|
|
||||||
|
// 💡 1. $casts 속성 추가:
|
||||||
|
// DB에 JSON 형태로 저장된 'role' 컬럼을 PHP에서 배열로 자동 변환합니다.
|
||||||
|
protected $casts = [
|
||||||
|
'role' => 'json-array',
|
||||||
|
];
|
||||||
|
|
||||||
public function getID(): string
|
public function getID(): string
|
||||||
{
|
{
|
||||||
return $this->attributes['id'];
|
return (string) $this->attributes['id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPassword(): string
|
public function getPassword(): string
|
||||||
{
|
{
|
||||||
return $this->attributes['passwd'];
|
return $this->attributes['passwd'];
|
||||||
}
|
}
|
||||||
public function getRole(): string
|
// $formDatas['passwd']에 평문 비밀번호가 들어있으면,
|
||||||
|
//Model->insert시 Entity 생성자($formDatas)가 setPasswd()를 자동으로 호출합니다.
|
||||||
|
public function setPasswd(string $password)
|
||||||
{
|
{
|
||||||
return $this->attributes['role'];
|
$this->attributes['passwd'] = password_hash($password, PASSWORD_BCRYPT);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 사용자의 역할을 배열 형태로 반환합니다.
|
||||||
|
* $casts에 의해 DB에서 읽어올 때 이미 배열로 변환되어 있습니다.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getRole(): array
|
||||||
|
{
|
||||||
|
// 💡 2. 반환 타입을 array로 변경하고,
|
||||||
|
// null일 경우를 대비해 빈 배열을 반환하도록 처리합니다.
|
||||||
|
return $this->attributes['role'] ?? [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,29 @@ class UserHelper extends CommonHelper
|
|||||||
case 'confirmpassword':
|
case 'confirmpassword':
|
||||||
$form = form_password($field, "", [...$extras]);
|
$form = form_password($field, "", [...$extras]);
|
||||||
break;
|
break;
|
||||||
|
case 'role':
|
||||||
|
// 💡 $value는 수정 폼 로드시 현재 Entity의 'role' 배열입니다.
|
||||||
|
// (old() 값이 있다면 old() 배열이 됩니다.)
|
||||||
|
$currentRoles = is_array($value) ? $value : [];
|
||||||
|
// 사용 가능한 모든 역할 목록 (Service 등에서 가져온다고 가정)
|
||||||
|
$allRoles = $viewDatas['control']['formOptions']['role'] ?? ROLE['USER'];
|
||||||
|
$form = '';
|
||||||
|
// 2. 각 역할에 대한 체크박스를 순회하며 생성
|
||||||
|
foreach ($allRoles as $roleValue => $roleLabel) {
|
||||||
|
|
||||||
|
// $roleLabel이 배열이 아닌 문자열만 있는 경우를 대비
|
||||||
|
if (is_int($roleValue)) {
|
||||||
|
$roleValue = $roleLabel;
|
||||||
|
$roleLabel = ucfirst($roleValue);
|
||||||
|
}
|
||||||
|
$checked = in_array($roleValue, $currentRoles);
|
||||||
|
// 3. name="role[]" 형태로 배열 데이터 전송 준비
|
||||||
|
$form .= '<label class="me-3">';
|
||||||
|
$form .= form_checkbox('role[]', $roleValue, $checked, array_merge(['id' => "role_{$roleValue}"], $extras));
|
||||||
|
$form .= " {$roleLabel}";
|
||||||
|
$form .= '</label>';
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
$form = parent::getFieldForm($field, $value, $viewDatas, $extras);
|
$form = parent::getFieldForm($field, $value, $viewDatas, $extras);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -16,12 +16,12 @@ return [
|
|||||||
'deleted_at' => "삭제일",
|
'deleted_at' => "삭제일",
|
||||||
],
|
],
|
||||||
"ROLE" => [
|
"ROLE" => [
|
||||||
"manager" => "관리자",
|
ROLE['USER']["MANAGER"] => "관리자",
|
||||||
"cloudflare" => "Cloudflare관리자",
|
ROLE['USER']["CLOUDFLARE"] => "Cloudflare관리자",
|
||||||
"firewall" => "firewall관리자",
|
ROLE['USER']["FIREWALL"] => "firewall관리자",
|
||||||
"security" => "보안관리자",
|
ROLE['USER']["SECURITY"] => "보안관리자",
|
||||||
"director" => "감독자",
|
ROLE['USER']["DIRECTOR"] => "감독자",
|
||||||
"master" => "마스터",
|
ROLE['USER']["MASTER"] => "마스터",
|
||||||
],
|
],
|
||||||
"STATUS" => [
|
"STATUS" => [
|
||||||
STATUS['AVAILABLE'] => "사용중",
|
STATUS['AVAILABLE'] => "사용중",
|
||||||
|
|||||||
@ -64,149 +64,104 @@ abstract class CommonModel extends Model
|
|||||||
{
|
{
|
||||||
return $this->useAutoIncrement;
|
return $this->useAutoIncrement;
|
||||||
}
|
}
|
||||||
//Primary Key로 uuid를 사용시 해당 모델에 아래 변수 반드시 추가 필요
|
/**
|
||||||
// protected $useAutoIncrement = false;
|
* Entity 삽입을 처리하고, $useAutoIncrement가 false일 경우 UUID를 자동으로 생성합니다.
|
||||||
// protected $beforeInsert = ['generateUUID'];
|
* @param object|array $data Entity 객체 또는 데이터 배열
|
||||||
// allowedFields에는 PK넣으면 않됨, Column Type: CHAR(36)
|
* @param bool $returnID 삽입 후 ID를 반환할지 여부 (자동 증가 키일 경우 true)
|
||||||
//
|
* @return bool|int|string
|
||||||
final protected function generateUUID(): string
|
*/
|
||||||
|
public function insert($data = null, bool $returnID = true)
|
||||||
{
|
{
|
||||||
$data = random_bytes(16);
|
// 1. 공통 전처리 로직 (예: 모든 모델에 대한 로그 기록, 공통 필드 설정 등)
|
||||||
// UUID version 4 (random)
|
$data = $this->preProcessData($data);
|
||||||
$data[6] = chr(ord($data[6]) & 0x0f | 0x40); // version 0100
|
|
||||||
$data[8] = chr(ord($data[8]) & 0x3f | 0x80); // variant 10
|
// 2. PK 자동 할당 로직
|
||||||
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
|
if (!$this->useAutoIncrement) {
|
||||||
}
|
$data = $this->ensurePrimaryKey($data);
|
||||||
public function getFormRule(string $action, string $field): string
|
|
||||||
{
|
|
||||||
if (is_array($field)) {
|
|
||||||
throw new \Exception(__FUNCTION__ . "=> field가 array 입니다.\n" . var_export($field, true));
|
|
||||||
}
|
}
|
||||||
switch ($field) {
|
|
||||||
case $this->getPKField():
|
// 3. BaseModel의 insert 호출
|
||||||
// 수동입력인 경우
|
// 문자열 PK일 경우, $returnID를 false로 넘겨서 ID 반환을 강제하지 않는 것이 좋습니다.
|
||||||
if (!$this->useAutoIncrement) {
|
$baseReturn = parent::insert($data, $this->useAutoIncrement);
|
||||||
$rule = "required|regex_match[/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/]";
|
|
||||||
$rule .= in_array($action, ["create", "create_form"]) ? "|is_unique[" . $this->getTable() . "." . $field . "]" : "";
|
// 4. 후처리 및 반환
|
||||||
} else {
|
|
||||||
$rule = "required|numeric";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case $this->getTitleField():
|
|
||||||
$rule = "required|trim|string";
|
|
||||||
break;
|
|
||||||
case "code":
|
|
||||||
// a-zA-Z → 영문 대소문자,0-9 → 숫자,가-힣 → 한글 완성형,\- → 하이픈
|
|
||||||
$rule = "required|regex_match[/^[a-zA-Z0-9가-힣\-]+$/]|min_length[4]|max_length[20]";
|
|
||||||
$rule .= in_array($action, ["create", "create_form"]) ? "|is_unique[" . $this->getTable() . "." . $field . "]" : "";
|
|
||||||
break;
|
|
||||||
case 'picture':
|
|
||||||
$rule = "is_image[{$field}]|mime_in[{$field},image/jpg,image/jpeg,image/gif,image/png,image/webp]|max_size[{$field},300]|max_dims[{$field},2048,768]";
|
|
||||||
break;
|
|
||||||
case "updated_at":
|
|
||||||
case "created_at":
|
|
||||||
case "deleted_at":
|
|
||||||
$rule = "permit_empty|valid_date";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$rule = "permit_empty|trim|string";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $rule;
|
|
||||||
}
|
|
||||||
protected function convertFormDatas(string $action, string $field, array $formDatas): mixed
|
|
||||||
{
|
|
||||||
// 필드 값 존재 여부 확인
|
|
||||||
$value = array_key_exists($field, $formDatas) ? $formDatas[$field] : null;
|
|
||||||
switch ($field) {
|
|
||||||
case $this->getPKField():
|
|
||||||
// 수동입력인 경우
|
|
||||||
if (!$this->useAutoIncrement) {
|
|
||||||
$randomBytes = bin2hex(random_bytes(32));
|
|
||||||
$value = sprintf(
|
|
||||||
'%08s-%04s-%04x-%04x-%12s',
|
|
||||||
substr($randomBytes, 0, 8),
|
|
||||||
substr($randomBytes, 8, 4),
|
|
||||||
substr($randomBytes, 12, 4),
|
|
||||||
substr($randomBytes, 16, 4),
|
|
||||||
substr($randomBytes, 20, 12)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "editor":
|
|
||||||
case "detail":
|
|
||||||
case "content":
|
|
||||||
case "discription":
|
|
||||||
case "history":
|
|
||||||
if ($value !== '' && $value !== null) {
|
|
||||||
$value = htmlentities($value, ENT_QUOTES, 'UTF-8');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
//기본 기능
|
|
||||||
public function create(array $formDatas): mixed
|
|
||||||
{
|
|
||||||
$convertedFormDatas = [];
|
|
||||||
foreach ($this->allowedFields as $field) {
|
|
||||||
$value = $this->convertFormDatas(
|
|
||||||
__FUNCTION__,
|
|
||||||
$field,
|
|
||||||
$formDatas
|
|
||||||
);
|
|
||||||
if ($value !== '' && $value !== null) {
|
|
||||||
$convertedFormDatas[$field] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 최종 저장 시 오류 발생하면
|
|
||||||
// dd($convertedFormDatas);
|
|
||||||
if (!$this->save($convertedFormDatas)) {
|
|
||||||
$message = sprintf(
|
|
||||||
"\n------%s 오류-----\n%s\n%s\n------------------------------\n",
|
|
||||||
__METHOD__,
|
|
||||||
var_export($this->errors(), true),
|
|
||||||
$this->getLastQuery()
|
|
||||||
);
|
|
||||||
log_message('error', $message);
|
|
||||||
throw new \Exception($message);
|
|
||||||
}
|
|
||||||
//Model별 returntype형의 Entity 호출
|
|
||||||
if (!class_exists($this->returnType)) {
|
|
||||||
throw new \RuntimeException(__METHOD__ . "에서 returnType: {$this->returnType}이 정의되지 않았습니다.");
|
|
||||||
}
|
|
||||||
$entity = new $this->returnType($convertedFormDatas);
|
|
||||||
// primaryKey가 자동입력이면
|
|
||||||
if ($this->useAutoIncrement) {
|
if ($this->useAutoIncrement) {
|
||||||
$pkField = $this->getPKField();
|
// 정수 PK: BaseModel이 반환한 새로운 ID를 그대로 반환
|
||||||
$entity->$pkField = $this->getInsertID();
|
return $baseReturn;
|
||||||
|
} else {
|
||||||
|
// 문자열 PK: BaseModel의 insert는 성공 시 true/1을 반환. true로 통일하여 반환
|
||||||
|
return $baseReturn !== false;
|
||||||
}
|
}
|
||||||
return $entity;
|
|
||||||
}
|
}
|
||||||
public function modify(mixed $entity, array $formDatas): mixed
|
|
||||||
|
/**
|
||||||
|
* Entity나 데이터 배열을 받아서 필요하다면 Primary Key를 생성하여 할당합니다.
|
||||||
|
* @param object|array $data
|
||||||
|
* @return object|array
|
||||||
|
*/
|
||||||
|
protected function ensurePrimaryKey($data)
|
||||||
{
|
{
|
||||||
//수정일추가
|
$pkName = $this->primaryKey;
|
||||||
$formDatas['updated_at'] = date("Y-m-d H:i:s");
|
$entityData = is_object($data) ? $data->attributes : (array) $data;
|
||||||
foreach (array_keys($formDatas) as $field) {
|
|
||||||
$value = $this->convertFormDatas(
|
// PK가 설정되어 있지 않은 경우
|
||||||
__FUNCTION__,
|
if (empty($entityData[$pkName])) {
|
||||||
$field,
|
$newUuid = service('uuid')->uuid4()->toString();
|
||||||
$formDatas
|
|
||||||
);
|
if (is_object($data)) {
|
||||||
if ($entity->$field !== $value) {
|
// Entity 객체일 경우 __set()을 통해 Setter를 호출하며 할당
|
||||||
$entity->$field = $value;
|
$data->$pkName = $newUuid;
|
||||||
|
} else {
|
||||||
|
// 배열일 경우 배열에 할당
|
||||||
|
$data[$pkName] = $newUuid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 최종 저장 시 오류 발생하면
|
return $data;
|
||||||
if (!$this->save($entity)) {
|
}
|
||||||
$message = sprintf(
|
|
||||||
"\n------%s 오류-----\n%s\n------------------------------\n",
|
/**
|
||||||
__METHOD__,
|
* 모든 삽입/수정 작업 전 공통 로직을 처리하는 확장 지점.
|
||||||
var_export($this->errors(), true)
|
*/
|
||||||
);
|
protected function preProcessData($data)
|
||||||
log_message('error', $message);
|
{
|
||||||
throw new \Exception($message);
|
// 예: $data['data']['updated_by'] = session('user_id');
|
||||||
}
|
return $data;
|
||||||
return $entity;
|
}
|
||||||
|
|
||||||
|
// ******************************************************
|
||||||
|
// 2. UPDATE 및 DELETE 확장
|
||||||
|
// ******************************************************
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BaseModel의 update 메서드를 호출하기 전/후에 공통 로직을 적용하는 확장 지점.
|
||||||
|
* @param array|int|string|null $id
|
||||||
|
* @param array|object|null $data
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function update($id = null, $data = null): bool
|
||||||
|
{
|
||||||
|
// 1. 업데이트 전 공통 로직 (preUpdate 이벤트)
|
||||||
|
$data = $this->preProcessData($data);
|
||||||
|
|
||||||
|
// 2. BaseModel의 update 호출
|
||||||
|
return parent::update($id, $data);
|
||||||
|
|
||||||
|
// 3. 업데이트 후 공통 로직 (postUpdate 이벤트)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BaseModel의 delete 메서드를 호출하기 전/후에 공통 로직을 적용하는 확장 지점.
|
||||||
|
* @param array|int|string|null $id
|
||||||
|
* @param bool $purge
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function delete($id = null, bool $purge = false): bool
|
||||||
|
{
|
||||||
|
// 1. 삭제 전 공통 로직 (preDelete 이벤트)
|
||||||
|
|
||||||
|
// 2. BaseModel의 delete 호출
|
||||||
|
return parent::delete($id, $purge);
|
||||||
|
|
||||||
|
// 3. 삭제 후 공통 로직 (postDelete 이벤트)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,45 +40,6 @@ class TrafficModel extends CommonModel
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
public function getFormRule(string $action, string $field): string
|
public function getFormRule(string $action, string $field): string
|
||||||
{
|
|
||||||
if (is_array($field)) {
|
|
||||||
throw new \Exception(__FUNCTION__ . "=> field가 array 입니다.\n" . var_export($field, true));
|
|
||||||
}
|
|
||||||
switch ($field) {
|
|
||||||
case "user_uid":
|
|
||||||
case "clientinfo_uid":
|
|
||||||
case "serverinfo_uid":
|
|
||||||
case "amount":
|
|
||||||
case "rack":
|
|
||||||
case "line":
|
|
||||||
$rule = "required|numeric";
|
|
||||||
break;
|
|
||||||
case "sale":
|
|
||||||
case "payment_uid":
|
|
||||||
$rule = "permit_empty|numeric";
|
|
||||||
break;
|
|
||||||
case "site":
|
|
||||||
case "location":
|
|
||||||
case "status":
|
|
||||||
$rule = "required|trim|string";
|
|
||||||
break;
|
|
||||||
case "billing_at":
|
|
||||||
case "start_at":
|
|
||||||
$rule = "required|valid_date";
|
|
||||||
break;
|
|
||||||
case "end_at":
|
|
||||||
$rule = "permit_empty|valid_date";
|
|
||||||
break;
|
|
||||||
case 'title':
|
|
||||||
case "history":
|
|
||||||
$rule = "permit_empty|trim|string";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$rule = parent::getFormRule($action, $field);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $rule;
|
|
||||||
}
|
|
||||||
//입력전 코드처리
|
//입력전 코드처리
|
||||||
final public function create(array $formDatas): ServiceEntity
|
final public function create(array $formDatas): ServiceEntity
|
||||||
{
|
{
|
||||||
|
|||||||
@ -27,50 +27,4 @@ class UserModel extends CommonModel
|
|||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
public function getFormRule(string $action, string $field): string
|
|
||||||
{
|
|
||||||
if (is_array($field)) {
|
|
||||||
throw new \Exception(__FUNCTION__ . "=> field가 array 입니다.\n" . var_export($field, true));
|
|
||||||
}
|
|
||||||
switch ($field) {
|
|
||||||
case "id":
|
|
||||||
$rule = "required|trim|min_length[4]|max_length[20]";
|
|
||||||
$rule .= in_array($action, ["create", "create_form"]) ? "|is_unique[{$this->table}.{$field}]" : "";
|
|
||||||
break;
|
|
||||||
case "passwd":
|
|
||||||
$rule = in_array($action, ["create", "create_form"]) ? "required|trim|string" : "permit_empty|trim|string";
|
|
||||||
break;
|
|
||||||
case "confirmpassword":
|
|
||||||
$rule = in_array($action, ["create", "create_form"]) ? "required|trim|string|matches[passwd]" : "permit_empty|trim|string|matches[passwd]";
|
|
||||||
break;
|
|
||||||
case "email":
|
|
||||||
$rule = "required|trim|valid_email";
|
|
||||||
$rule .= in_array($action, ["create", "create_form"]) ? "|is_unique[{$this->table}.{$field}]" : "";
|
|
||||||
break;
|
|
||||||
case "role":
|
|
||||||
$rule = "required|trim|string";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$rule = parent::getFormRule($action, $field);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $rule;
|
|
||||||
}
|
|
||||||
protected function convertFormDatas(string $action, string $field, array $formDatas): mixed
|
|
||||||
{
|
|
||||||
// 필드 값 존재 여부 확인
|
|
||||||
$value = array_key_exists($field, $formDatas) ? $formDatas[$field] : null;
|
|
||||||
switch ($field) {
|
|
||||||
case "passwd":
|
|
||||||
$value = password_hash($value, PASSWORD_DEFAULT);
|
|
||||||
break;
|
|
||||||
case "confirmpassword":
|
|
||||||
$value = password_hash($value, PASSWORD_DEFAULT);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$value = parent::convertFormDatas($action, $field, $formDatas);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,13 +50,31 @@ class UserService extends CommonService
|
|||||||
{
|
{
|
||||||
// DTO 객체를 배열로 변환하여 검증기에 전달
|
// DTO 객체를 배열로 변환하여 검증기에 전달
|
||||||
$formDatas = (array) $dto;
|
$formDatas = (array) $dto;
|
||||||
|
// dd($formDatas);
|
||||||
if (!service('validation')->setRules($this->getFormRules(__FUNCTION__))->run($formDatas)) {
|
if (!service('validation')->setRules($this->getFormRules(__FUNCTION__))->run($formDatas)) {
|
||||||
// 검증 실패 시, ValidationException을 던집니다.
|
|
||||||
throw new ValidationException(implode("\n", service('validation')->getErrors()));
|
throw new ValidationException(implode("\n", service('validation')->getErrors()));
|
||||||
}
|
}
|
||||||
$formDatas['role'] = implode(DEFAULTS["DELIMITER_ROLE"], $formDatas['role']);
|
$entity = new UserEntity($formDatas);
|
||||||
$entity = $this->model->create($formDatas);
|
$result = $this->model->insert($entity);
|
||||||
return $entity;
|
if (!$result) {
|
||||||
|
throw new \Exception("{$entity->getTitle()} 등록 중 DB 오류가 발생하였습니다.");
|
||||||
|
}
|
||||||
|
// 💡 PK 타입에 따른 최종 Entity 반환 로직 분기
|
||||||
|
if ($this->model->useAutoIncrement) {
|
||||||
|
// 1. 정수 PK인 경우: $result는 ID 번호이므로, 저장된 레코드를 DB에서 다시 조회합니다.
|
||||||
|
// (자동 설정된 필드(created_at 등)를 포함하기 위해 재조회)
|
||||||
|
$savedEntity = $this->model->find($result);
|
||||||
|
} else {
|
||||||
|
// 2. 문자열 PK인 경우: $result는 true/1 이므로,
|
||||||
|
// 이미 ID가 설정된 $entity 객체를 반환하거나, ID로 재조회합니다.
|
||||||
|
// Entity에 모든 필드(created_at 등)가 설정되지 않았다면 재조회가 안전합니다.
|
||||||
|
$pkValue = $entity->{$this->model->primaryKey};
|
||||||
|
$savedEntity = $this->model->find($pkValue);
|
||||||
|
}
|
||||||
|
if (!$savedEntity) {
|
||||||
|
throw new \Exception("등록된 데이터를 찾을 수 없습니다.");
|
||||||
|
}
|
||||||
|
return $savedEntity;
|
||||||
}
|
}
|
||||||
// protected function modify_process(mixed $entity, array $formDatas): UserEntity
|
// protected function modify_process(mixed $entity, array $formDatas): UserEntity
|
||||||
// {
|
// {
|
||||||
|
|||||||
@ -1,22 +1,23 @@
|
|||||||
<?= $this->extend(LAYOUTS[$viewDatas['control']['layout']]['path']) ?>
|
<?= $this->extend(LAYOUTS[$viewDatas['control']['layout']]['path']) ?>
|
||||||
<?= $this->section('content') ?>
|
<?= $this->section('content') ?>
|
||||||
<?php if ($error = session('error')): echo $viewDatas['service']->getHelper()->alertTrait($error) ?><?php endif ?>
|
<?php if (session('error')): echo $viewDatas['control']['helper']->alertTrait(session('error')) ?><?php endif ?>
|
||||||
<div id="container" class="content">
|
<div id="container" class="content">
|
||||||
<div class="form_top"><?= $this->include("templates/{$viewDatas['control']['layout']}/form_content_top"); ?></div>
|
<div class="form_top"><?= $this->include("templates/{$viewDatas['control']['layout']}/form_content_top"); ?></div>
|
||||||
<?= form_open(current_url(), ['id' => 'action_form', ...$viewDatas['forms']['attributes']], $viewDatas['forms']['hiddens']) ?>
|
<?= form_open(current_url(), $viewDatas['forms']['attributes'], $viewDatas['forms']['hiddens']) ?>
|
||||||
<div class="action_form">
|
<div class="action_form">
|
||||||
<table class="table table-bordered">
|
<table class="table table-bordered">
|
||||||
<?php foreach ($viewDatas['control']['formFields'] as $field): ?>
|
<?php foreach ($viewDatas['control']['formFields'] as $field): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<th nowrap class="text-end"><?= $viewDatas['service']->getHelper()->getFieldLabel($field, lang("{$viewDatas['class_path']}.label.{$field}"), $viewDatas) ?></th>
|
<th nowrap class="text-end"><?= $viewDatas['control']['helper']->getFieldLabel($field, "", $viewDatas) ?></th>
|
||||||
|
<?= dd($viewDatas); ?>
|
||||||
<td nowrap class="text-start">
|
<td nowrap class="text-start">
|
||||||
<?= $viewDatas['service']->getHelper()->getFieldForm($field, old($field) ?? $viewDatas['entity']->$field ?? null, $viewDatas) ?>
|
<?= $viewDatas['control']['helper']->getFieldForm($field, old($field) ?? ($viewDatas['control']['entity']->$field ?? null), $viewDatas) ?>
|
||||||
<div><?= validation_show_error($field); ?></div>
|
<span><?= validation_show_error($field); ?></span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</table>
|
</table>
|
||||||
<div class="text-center"><?= form_submit("", '수정', ["class" => "btn btn-outline btn-primary"]) ?></div>
|
<div class="text-center"><?= form_submit('', '입력', array("class" => "btn btn-outline btn-primary")); ?></div>
|
||||||
<?= form_close(); ?>
|
<?= form_close(); ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="form_bottom"><?= $this->include("templates/{$viewDatas['control']['layout']}/form_content_bottom"); ?></div>
|
<div class="form_bottom"><?= $this->include("templates/{$viewDatas['control']['layout']}/form_content_bottom"); ?></div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user