ป้ายกำกับ: ฟังก์ชัน

PHP Union Types: เขียนโค้ดให้ยืดหยุ่น แต่ปลอดภัยยิ่งขึ้นPHP Union Types: เขียนโค้ดให้ยืดหยุ่น แต่ปลอดภัยยิ่งขึ้น

ย้อนกลับไปใน 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) และน่าทำงานด้วยขึ้นอีกหลายเท่าครับ!


อ่านเพิ่มเติม