ฟอร์มสมัครสมาชิก ระบบลงทะเบียน หรือระบบของหน่วยงาน มักให้ผู้ใช้กรอกเลขบัตรประชาชน ถ้าเราเช็คตั้งแต่ตอนกรอกว่าเลขนั้นเป็นไปได้จริง ก็กันเลขที่พิมพ์ผิดไว้ได้ก่อนเข้าระบบ ผมทำแพ็กเกจ phattarachai/thai-id-card-validation ไว้ให้เช็คเรื่องนี้ใน Laravel ด้วย Rule ตัวเดียว
ติดตั้ง
composer require phattarachai/thai-id-card-validation
เวอร์ชัน 2.0 ใช้กับ PHP 8.3 ขึ้นไป และ Laravel 12 หรือ 13
ใช้ใน Laravel
ใส่ ThaiIdCardRule ไว้ใน rule ของ field ที่อยากเช็ค
use Phattarachai\ThaiIdCardValidation\ThaiIdCardRule;
$request->validate([
'email' => ['required', 'email'],
'id_card_no' => ['bail', 'required', 'digits:13', new ThaiIdCardRule],
]);
ลองกรอกเลขตัวอย่าง 1737063686013 ดู เลขนี้ผ่าน ส่วน 1234567890123 ไม่ผ่าน ถ้าอยากได้เลขที่ผ่านไว้ทดสอบอีก สุ่มได้ที่ สุ่มเลขบัตรประชาชนสำหรับทดสอบระบบ
ตัดขีดกับช่องว่างที่ผู้ใช้พิมพ์มาก่อน validate
ผู้ใช้มักพิมพ์เลขบัตรแบบมีขีดหรือเว้นวรรค เช่น 1-7370-63686-01-3 ซึ่ง Rule ไม่รับ เพราะค่าที่เราจะบันทึกลงฐานข้อมูลควรเป็นตัวเลขล้วนอยู่ดี ใน Form Request เราตัดขีดกับช่องว่างออกก่อน validate ได้ใน prepareForValidation()
use Illuminate\Foundation\Http\FormRequest;
use Phattarachai\ThaiIdCardValidation\ThaiIdCardRule;
class RegisterRequest extends FormRequest
{
protected function prepareForValidation(): void
{
$this->merge([
'id_card_no' => str_replace(['-', ' '], '', (string) $this->input('id_card_no')),
]);
}
public function rules(): array
{
return [
'id_card_no' => ['bail', 'required', 'digits:13', new ThaiIdCardRule],
];
}
}
เราตัดแค่ขีดกับช่องว่าง ไม่ใช้ preg_replace('/\D/', '', …) ที่ลบทุกตัวที่ไม่ใช่ตัวเลข เพราะแบบนั้นค่าอย่าง abc1737063686013 จะเหลือแต่ตัวเลขแล้วผ่านไปได้
อยากเปลี่ยนข้อความ error
ข้อความเริ่มต้นคือ รหัสบัตรประชาชนไม่ถูกต้อง เปลี่ยนได้สองทาง
ถ้าอยากเปลี่ยนแค่ field เดียว ส่งข้อความเข้าไปตอนสร้าง Rule ได้เลย ใส่ :attribute ได้เหมือน rule อื่น ๆ หรือจะส่งเป็น lang key ก็ได้
'id_card_no' => ['bail', 'required', 'digits:13', new ThaiIdCardRule('เลขบัตรประชาชนไม่ถูกต้อง กรุณาตรวจสอบอีกครั้ง')],
ถ้าอยากให้ใช้ข้อความเดียวกันทั้งแอป ให้เพิ่ม key thai_id_card ในไฟล์ validation.php ของแต่ละภาษา Rule จะหยิบข้อความตาม locale ของแอปให้เอง
'thai_id_card' => ':attribute ไม่ใช่เลขบัตรประชาชนที่ถูกต้อง',
'thai_id_card' => 'The :attribute must be a valid Thai ID card number.',
ถ้ามีทั้งสองแบบ Rule ใช้ข้อความที่ส่งเข้า constructor ก่อน
ใช้นอก Laravel ได้ด้วย
ใน PHP ทั่วไปหรือ framework อื่น เรียกคลาส ThaiIdCard ตรง ๆ
use Phattarachai\ThaiIdCardValidation\ThaiIdCard;
(new ThaiIdCard)->validate('1737063686013');
// true
(new ThaiIdCard)->validate('1234567890123');
// false
validate() รับเลขเป็น string หรือ int ค่าอื่นอย่าง null หรือ array จะได้ false กลับมา
เลขแต่ละหลักบอกอะไร
- หลักที่ 1 ระบุประเภทของบุคคล แบ่งเป็น 8 ประเภท
- ประเภท 1 คนที่มีสัญชาติไทยและแจ้งเกิดภายในเวลาที่กำหนด
- ประเภท 2 คนที่มีสัญชาติไทยแต่แจ้งเกิดเกินเวลาที่กำหนด
- ประเภท 3 คนไทยหรือคนต่างด้าวที่มีชื่ออยู่ในทะเบียนบ้านก่อนวันที่ 31 พฤษภาคม 2527
- ประเภท 4 คนไทยหรือคนต่างด้าวที่แจ้งย้ายเข้าโดยยังไม่มีเลขประจำตัว
- ประเภท 5 คนที่ได้รับเพิ่มชื่อเข้าทะเบียนบ้านภายหลัง เช่น ตกสำรวจ
- ประเภท 6 คนที่เข้าเมืองโดยไม่ถูกกฎหมาย หรือเข้าเมืองถูกกฎหมายแต่อยู่ชั่วคราว
- ประเภท 7 บุตรของคนประเภท 6 ที่เกิดในประเทศไทย
- ประเภท 8 คนต่างด้าวที่ได้สัญชาติไทยโดยถูกต้องตามกฎหมาย
- หลักที่ 2–5 ระบุสถานที่ออกเลข โดยหลักที่ 2–3 คือจังหวัด และหลักที่ 4–5 คืออำเภอ
- หลักที่ 6–10 คือกลุ่มของบุคคล
- หลักที่ 11–12 คือลำดับที่ของบุคคลในกลุ่มนั้น
- หลักที่ 13 คือหลักตรวจสอบ (check digit)
วิธีคำนวณหลักตรวจสอบ
เอา 12 หลักแรกคูณด้วยน้ำหนักที่ไล่ลงจาก 13 ถึง 2 แล้วบวกกัน
ผลรวม = (หลักที่ 1 × 13) + (หลักที่ 2 × 12) + (หลักที่ 3 × 11) + (หลักที่ 4 × 10)
+ (หลักที่ 5 × 9) + (หลักที่ 6 × 8) + (หลักที่ 7 × 7) + (หลักที่ 8 × 6)
+ (หลักที่ 9 × 5) + (หลักที่ 10 × 4) + (หลักที่ 11 × 3) + (หลักที่ 12 × 2)
หลักที่ 13 = (11 − (ผลรวม mod 11)) mod 10
ตัวอย่าง เลข 1737063686013
ผลรวม = (1 × 13) + (7 × 12) + (3 × 11) + (7 × 10) + (0 × 9) + (6 × 8)
+ (3 × 7) + (6 × 6) + (8 × 5) + (6 × 4) + (0 × 3) + (1 × 2)
= 13 + 84 + 33 + 70 + 0 + 48 + 21 + 36 + 40 + 24 + 0 + 2
= 371
หลักที่ 13 = (11 − (371 mod 11)) mod 10
= (11 − 8) mod 10
= 3
หลักที่ 13 ของเลขนี้คือ 3 ตรงกับที่คำนวณได้ เลขนี้จึงผ่าน






