วัน: 20 กุมภาพันธ์ 2022

PHP: Nullsafe Operator (?->)PHP: Nullsafe Operator (?->)

ก่อนหน้าที่จะมี PHP 8.0 เวลาที่เราต้องการเข้าถึง Method หรือ Property ของ Object ที่ร้อยเรียงกันเป็นทอด ๆ (Chaining) ยิ่งถ้าข้อมูลนั้นมาจาก Database หรือ API ที่มีโอกาสเป็น null เราจะต้องเขียนโค้ดตรวจสอบกันอย่างยาวเหยียดเพื่อความปลอดภัย
ตัวอย่างโค้ดแบบเดิม

// สมมติว่าเราต้องการชื่อประเทศของผู้ใช้งาน
$country = null;

if ($user !== null) {
    $profile = $user->getProfile();
    if ($profile !== null) {
        $address = $profile->getAddress();
        if ($address !== null) {
            $country = $address->country;
        }
    }
}

จะเห็นว่าโค้ดมีความซ้อนเป็นชั้น ๆ (Nested If) ดูรก และอ่านยากมาก หรือบางคนอาจจะเลี่ยงไปใช้แบบนี้

$country = ($user && $user->getProfile() && $user->getProfile()->getAddress()) 
    ? $user->getProfile()->getAddress()->country 
    : null;

ถึงจะสั้นลง แต่ก็ยังต้องเขียนซ้ำ ๆ และเสี่ยงต่อการพิมพ์ผิดอยู่ดี


พระเอกขี่ม้าขาว: Nullsafe Operator (?->)

ตั้งแต่ PHP 8.0 เป็นต้นมา เราสามารถยุบโค้ดด้านบนทั้งหมดให้เหลือเพียงแค่ บรรทัดเดียว ได้ด้วยการเติมเครื่องหมายคำถาม ? ไว้หน้าลูกศร -> ครับ

ตัวอย่างโค้ดแบบใหม่

$country = $user?->getProfile()?->getAddress()?->country;

มันทำงานยังไง?

กลไกของมันเข้าใจง่ายมากครับ PHP จะไล่เช็คจากซ้ายไปขวา

  1. เช็คว่า $user เป็น null ไหม? ถ้าใช่ มันจะหยุดทำงานทันทีแล้วคืนค่า null ให้變數 $country
  2. ถ้า $user ไม่ใช่ null มันก็จะไปเช็ค $user->getProfile() ต่อ
  3. ทำแบบนี้ไปเรื่อย ๆ จนสุดสาย

💡 ข้อดี: ถ้าตัวใดตัวหนึ่งในสาย (Chain) เป็น null โค้ดจะไม่พัง (ไม่เกิด Fatal Error) แต่จะส่งกลับเป็น null ทันที เรียกว่าเกิดกระบวนการ Short-circuiting


ความแตกต่างระหว่าง ?-> (Nullsafe) กับ ?? (Null Coalescing)

สองตัวนี้มักจะใช้คู่กัน แต่อย่าสับสนหน้าที่ของมันนะครับ

  • ?-> (Nullsafe): ใช้เพื่อ “ทางผ่าน” ในการเข้าถึง Property/Method ของ Object อย่างปลอดภัย (ถ้าเจอ null ให้หยุดเดินต่อ)
  • ?? (Null Coalescing): ใช้เพื่อ “กำหนดค่า Default” ในกรณีที่ผลลัพธ์สุดท้ายเป็น null หรือไม่มีอยู่จริง

การใช้งานร่วมกันแบบทรงพลัง

// ถ้าตรงไหนสักแห่งเป็น null ให้ระบุประเทศเป็น 'Unknown' แทน
$country = $user?->getProfile()?->getAddress()?->country ?? 'Unknown';

ข้อจำกัดที่ควรรู้ (Caveats)

แม้ ?-> จะเทพแค่ไหน แต่ก็มีข้อจำกัดที่ต้องระวังอยู่ 2 เรื่องหลัก ๆ ครับ

  • ใช้กับ write operations (การเขียนค่า) ไม่ได้
    เราใช้ Nullsafe เพื่อ “อ่านค่า” เท่านั้น ไม่สามารถใช้ฝั่งซ้ายของเครื่องหมายเท่ากับเพื่อเปลี่ยนค่าได้
    $user?->getProfile()?->address = 'Bangkok'; // ❌ ทำไม่ได้! จะเกิด Compile error
    
  • ไม่ช่วยเรื่อง Array Key ที่ไม่มีอยู่จริง
    Nullsafe ทำงานกับ Object เท่านั้น หากคุณพยายามใช้เข้าถึง Key ของ Array ที่ไม่มีอยู่ จะยังเกิด Warning เหมือนเดิม
    $data = ['user' => null];
    // $data['user']?->profile; // ❌ อันนี้รอดเพราะตรวจสอบ object หลังชี้ไปที่ user
    // $data['profile']?->name; // ❌ อันนี้พังตั้งแต่ $data['profile'] แล้ว (Undefined array key)
    

สรุป

การมาของ Nullsafe Operator ช่วยให้โค้ด PHP ในปัจจุบันสะอาดขึ้น (Clean Code) อ่านง่ายขึ้น และลดโอกาสเกิดบั๊กประเภท Call to a member function on null ได้อย่างมหาศาล ถือเป็น Syntax Sugar ที่เปลี่ยนชีวิตนักพัฒนา PHP ให้มีความสุขขึ้นอย่างแท้จริงครับ!


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