allowedFields; } //Primary Key로 uuid를 사용시 해당 모델에 아래 변수 반드시 추가 필요 // protected $useAutoIncrement = false; // protected $beforeInsert = ['generateUUID']; // allowedFields에는 PK넣으면 않됨, Column Type: CHAR(36) // final protected function generateUUID(): string { $data = random_bytes(16); // UUID version 4 (random) $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // version 0100 $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // variant 10 return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); } final protected function getFormFieldRules(string $action, array $fields, $rules = []): array { foreach ($fields as $field) { $rules[$field] = $this->getFormFieldRule($action, $field); } return $rules; } public function getFormFieldRule(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(): // 수동입력인 경우 if (!$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->table}.{$field}]" : ""; } else { $rule = "required|numeric"; } break; case $this->getTitleField(): $rule = "required|trim|string"; 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 = "if_exist|valid_date"; break; default: $rule = "if_exist|trim|string"; break; } return $rule; } // create, modify 직전 작업용 작업 protected function convertEntityData(string $action, string $field, array $formDatas, mixed $entity): mixed { switch ($field) { case $this->getPKField(): // $formDatas에 전달된 값이 없는 경우 if (!array_key_exists($field, $formDatas)) { $randomBytes = bin2hex(random_bytes(32)); $entity->$field = 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) ); } else { $entity->$field = $formDatas[$field]; } break; case "editor": // content 등 textarea를 사용한 Field case "content": // content 등 textarea를 사용한 Field case "discription": // content 등 textarea를 사용한 Field $entity->$field = htmlentities($formDatas[$field], ENT_QUOTES); break; default: if ($this->getFormFieldRule($action, $field) != "if_exist|numeric") { if (array_key_exists($field, $formDatas) && $formDatas[$field] !== '') { $entity->$field = $formDatas[$field]; } } else { $entity->$field = $formDatas[$field]; } break; } return $entity; } private function save_process(mixed $entity): mixed { // 최종 변경사항이 없으면 if (!$entity->hasChanged()) { return $entity; } // 최종 저장 시 오류 발생하면 if (!$this->save($entity)) { $message = sprintf( "\n------%s 오류-----\n%s\n%s\n------------------------------\n", __FUNCTION__, $this->getLastQuery(), var_export($this->errors(), true) ); LogCollector::error($message); throw new \Exception($message); } return $entity; } final function create(array $formDatas, mixed $entity): mixed { // Field에 맞는 Validation Rule 재정의 $this->setValidationRules($this->getFormFieldRules(__FUNCTION__, $this->allowedFields)); LogCollector::debug("입력내용"); LogCollector::debug(var_export($formDatas, true)); foreach (array_keys($formDatas) as $field) { $entity = $this->convertEntityData(__FUNCTION__, $field, $formDatas, $entity); } // primaryKey가 자동입력이 아니면 if (!$this->useAutoIncrement) { $pkField = $this->getPKField(); $entity->$pkField = $this->generateUUID(); } $entity = $this->save_process($entity); // primaryKey가 자동입력이면 if ($this->useAutoIncrement) { $pkField = $this->getPKField(); $entity->$pkField = $this->getInsertID(); } LogCollector::debug("[{$entity->getPK()}/{$entity->getTitle()}] 입력 후 내용"); LogCollector::debug(var_export($entity->toArray(), true)); return $entity; } final function modify(mixed $entity, array $formDatas): mixed { // Field에 맞는 Validation Rule 재정의 $this->setValidationRules($this->getFormFieldRules(__FUNCTION__, $this->allowedFields)); // 저장하기 전에 데이터 값 변경이 필요한 Field LogCollector::debug("[{$entity->getPK()}/{$entity->getTitle()}] 변경 전 내용"); LogCollector::debug(var_export($formDatas, true)); LogCollector::debug(var_export($entity->toArray(), true)); foreach (array_keys($formDatas) as $field) { $entity = $this->convertEntityData(__FUNCTION__, $field, $formDatas, $entity); } //수정일추가 $entity->setUpdatedAt(date("Y-m-d H:i:s")); LogCollector::debug("[{$entity->getPK()}/{$entity->getTitle()}] 변경 후 내용"); LogCollector::debug(var_export($entity->toArray(), true)); return $this->save_process($entity); } //List 검색용 public function setList_WordFilter(string $word): void { $this->orLike($this->getTable() . "." . $this->getTitleField(), $word, 'both'); } }