Files
gravity/บริหารจัดการคิวนวดแผนไทย/app/Helpers/Validator.php
T
2026-09-16 23:20:08 +07:00

146 lines
5.4 KiB
PHP

<?php
namespace App\Helpers;
/**
* Class Validator
* Enterprise Data Validation Engine (Input & API Request Guard)
*
* @package App\Helpers
*/
class Validator
{
private array $errors = [];
private array $data;
public function __construct(array $data)
{
$this->data = $data;
}
/**
* Create and run validation rules
*
* @param array $data
* @param array $rules Rule definitions e.g. ['national_id' => 'required|cid_13']
* @return self
*/
public static function make(array $data, array $rules): self
{
$validator = new self($data);
foreach ($rules as $field => $ruleStr) {
$ruleList = explode('|', $ruleStr);
foreach ($ruleList as $rule) {
if (strpos((string)$rule, ':') !== false) {
[$ruleName, $param] = explode(':', $rule, 2);
$validator->applyRule($field, $ruleName, $param);
} else {
$validator->applyRule($field, $rule, null);
}
}
}
return $validator;
}
private function applyRule(string $field, string $rule, ?string $param): void
{
$val = $this->data[$field] ?? null;
if ($rule === 'required' && ($val === null || trim((string)$val) === '')) {
$this->addError($field, "ฟิลด์ {$field} เป็นข้อมูลที่ต้องระบุ (Required)");
return;
}
if ($val === null || trim((string)$val) === '') {
return; // ข้ามการตรวจสอบอื่นถ้าค่าเป็นว่างและไม่ได้เป็น required
}
switch ($rule) {
case 'cid_13':
if (!preg_match('/^[0-9]{13}$/', (string)$val)) {
$this->addError($field, "เลขบัตรประชาชนต้องเป็นตัวเลข 13 หลักเท่านั้น");
} elseif (!$this->verifyThaiIDChecksum((string)$val)) {
$this->addError($field, "เลขบัตรประชาชน 13 หลักไม่ถูกต้องตามสูตรคำนวณ Checksum");
}
break;
case 'numeric':
if (!is_numeric($val)) {
$this->addError($field, "ฟิลด์ {$field} ต้องเป็นตัวเลขเท่านั้น");
}
break;
case 'email':
if (!filter_var($val, FILTER_VALIDATE_EMAIL)) {
$this->addError($field, "รูปแบบอีเมลไม่ถูกต้อง");
}
break;
case 'min':
if (strlen((string)$val) < (int)$param) {
$this->addError($field, "ฟิลด์ {$field} ต้องมีความยาวอย่างน้อย {$param} ตัวอักษร");
}
break;
case 'max':
if (strlen((string)$val) > (int)$param) {
$this->addError($field, "ฟิลด์ {$field} ต้องมีความยาวไม่เกิน {$param} ตัวอักษร");
}
break;
case 'in':
$allowed = explode(',', (string)$param);
if (!in_array($val, $allowed, true)) {
$this->addError($field, "ค่าในฟิลด์ {$field} ไม่ถูกต้อง (ต้องเป็น: " . implode(', ', $allowed) . ")");
}
break;
case 'date':
if (!strtotime((string)$val)) {
$this->addError($field, "ฟิลด์ {$field} ต้องเป็นวันที่ที่ถูกต้อง (YYYY-MM-DD)");
}
break;
case 'time':
if (!preg_match('/^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/', (string)$val)) {
$this->addError($field, "ฟิลด์ {$field} ต้องเป็นเวลาที่ถูกต้อง (HH:MM หรือ HH:MM:SS)");
}
break;
case 'vas_score':
if (!is_numeric($val) || (int)$val < 0 || (int)$val > 10) {
$this->addError($field, "ระดับความปวด VAS Score ต้องเป็นตัวเลขระหว่าง 0 ถึง 10");
}
break;
}
}
/**
* ตรวจสอบ Checksum เลขบัตรประชาชนไทย 13 หลัก ตามหลักโมดูโล 11
*/
private function verifyThaiIDChecksum(string $cid): bool
{
if (strlen($cid) !== 13) return false;
$sum = 0;
for ($i = 0; $i < 12; $i++) {
$sum += (int)$cid[$i] * (13 - $i);
}
$checkDigit = (11 - ($sum % 11)) % 10;
return (int)$cid[12] === $checkDigit;
}
private function addError(string $field, string $msg): void
{
$this->errors[$field][] = $msg;
}
public function fails(): bool
{
return !empty($this->errors);
}
public function getErrors(): array
{
return $this->errors;
}
}