ย้อนกลับไปใน PHP เวอร์ชันเก่า ๆ เวลาเราต้องการให้ฟังก์ชันหนึ่งรองรับข้อมูลได้หลายประเภท (เช่น รับเป็นได้ทั้งตัวเลข int หรือทศนิยม float) สิ่งที่เรามักจะทำคือการละเว้นไม่ระบุ Type (Type Hinting) หรือเปลี่ยนไปใช้ข้อความอธิบายใน PHPDoc แทน เช่น / @param int|float $number */
แต่ตั้งแต่ PHP 8.0 เป็นต้นมา ชีวิตของนักพัฒนาเปลี่ยนไปในทางที่ดีขึ้นมากด้วยการมาของ Union Types ที่ช่วยให้เราสามารถระบุหลาย ๆ Type ให้กับตัวแปร, พารามิเตอร์ หรือค่า Return ได้โดยตรงในโค้ดเลยครับ
Union Types คืออะไร?
Union Types คือการประกาศว่า “ค่าในตำแหน่งนี้ สามารถเป็น Data Type ชนิดใดชนิดหนึ่งจากกลุ่มที่ระบุไว้ได้” โดยเราจะใช้เครื่องหมายแนวตั้ง | (Pipe) เป็นตัวคั่นระหว่าง Type ต่าง ๆ
ลองมาดูการเปรียบเทียบระหว่างแบบเก่าและแบบใหม่กันครับ
แบบเดิม (PHP 7.4 ลงไป)
ต้องพึ่งพา Comment เพื่อบอกให้โปรแกรมเมอร์คนอื่นรู้ หรือใช้ Tool ช่วยเช็กโค้ด
/**
* @param int|float $number
* @return int|float
*/
function square($number) {
return $number * $number;
}
แบบใหม่ (PHP 8.0+)
ระบุลงไปในระดับ Syntax ของภาษาเลย ถ้าระบบส่ง Type อื่นมา PHP จะแจ้ง Error ทันที
function square(int|float $number): int|float {
return $number * $number;
}
ตัวอย่างการใช้งานจริงที่พบบ่อย
รับค่าเป็น Object หรือ Null (Type|null)
แม้ว่าใน PHP 7.1 จะมี Nullable Types โดยใช้เครื่องหมาย ?Type แล้ว (เช่น ?string) แต่พอมี Union Types เราสามารถเขียน string|null ได้ ซึ่งให้ความหมายเหมือนกัน แต่มีความยืดหยุ่นกว่าเมื่อต้องการผสมกับ Type อื่น ๆ
function findUser(int $id): User|null {
// ค้นหาผู้ใช้ใน Database
// ถ้าเจอส่งกลับเป็น Object User ถ้าไม่เจอส่งกลับเป็น null
return $user ?? null;
}
ฟังก์ชันที่ทำงานสำเร็จจะส่งผลลัพธ์ แต่ถ้าล้มเหลวจะส่งเป็น false
ฟังก์ชันพื้นฐานของ PHP หลายตัว (เช่น strpos()) มักจะคืนค่ากลับมาเป็นตำแหน่งเดี่ยวๆ หรือไม่ก็ false ไปเลย เมื่อมี Union Types เราก็สร้างฟังก์ชันในลักษณะนี้ได้เองอย่างถูกต้อง
function uploadFile(array $file): string|bool {
if ($file['size'] > 5000000) {
return false; // ไฟล์ใหญ่เกินไป
}
// โค้ดอัปโหลดไฟล์...
return "/uploads/image.png";
}
กฎเหล็กที่ต้องรู้เกี่ยวกับ Union Types
แม้ว่า Union Types จะสะดวกมาก แต่ก็มีข้อจำกัดบางอย่างที่ PHP กำหนดไว้เพื่อป้องกันความสับสนครับ
- ห้ามใช้
voidร่วมกับ Type อื่น: เนื่องจากvoidหมายถึง “ห้ามส่งค่าใด ๆ กลับมาเลย” ดังนั้นการเขียนstring|voidจึงผิดหลักไวยากรณ์และจะเกิด Compile Error - ห้ามใช้
nullableซ้ำซ้อน: ถ้าคุณใช้|nullแล้ว ห้ามใส่เครื่องหมาย?ข้างหน้า Type อีก เช่น?string|int(แบบนี้ผิด) ต้องเขียนเป็นstring|int|null(แบบนี้ถูก) - Duplicate Types: ห้ามระบุ Type ซ้ำกัน เช่น
int|intหรือbool|false(เนื่องจากfalseเป็นส่วนหนึ่งของboolอยู่แล้ว)
สรุปข้อดีของ Union Types
- Code as Documentation: โค้ดอธิบายตัวเองได้ชัดเจน ไม่ต้องเดาจาก Comment อีกต่อไป
- Catch Bugs Early: ตรวจพบข้อผิดพลาดของการส่งข้อมูลผิดประเภทได้ทันทีตั้งแต่ตอนรันโปรแกรม
- Better IDE Support: ตัวช่วยเขียนโค้ด (เช่น VS Code, PHPStorm) สามารถแนะนำ (Auto-complete) และแจ้งเตือนจุดผิดพลาดได้อย่างแม่นยำขึ้น
หากคุณกำลังพัฒนาโปรเจกต์ด้วย PHP 8.0 ขึ้นไป การนำ Union Types ไปปรับใช้จะช่วยให้ Codebase ของคุณมีความแข็งแรง (Robust) และน่าทำงานด้วยขึ้นอีกหลายเท่าครับ!
อ่านเพิ่มเติม