ก่อนหน้าที่จะมี PHP 8.0 เวลาที่เราต้องการเข้าถึง Method หรือ Property ของ Object ที่ร้อยเรียงกันเป็นทอด ๆ (Chaining) ยิ่งถ้าข้อมูลนั้นมาจาก Database หรือ API ที่มีโอกาสเป็น null เราจะต้องเขียนโค้ดตรวจสอบกันอย่างยาวเหยียดเพื่อความปลอดภัย
ตัวอย่างโค้ดแบบเดิม
PHP
PHP
// สมมติว่าเราต้องการชื่อประเทศของผู้ใช้งาน
$country = null;
if ($user !== null) {
$profile = $user->getProfile();
if ($profile !== null) {
$address = $profile->getAddress();
if ($address !== null) {
$country = $address->country;
}
}
}
จะเห็นว่าโค้ดมีความซ้อนเป็นชั้น ๆ (Nested If) ดูรก และอ่านยากมาก หรือบางคนอาจจะเลี่ยงไปใช้แบบนี้
PHP
PHP
$country = ($user && $user->getProfile() && $user->getProfile()->getAddress())
? $user->getProfile()->getAddress()->country
: null;
ถึงจะสั้นลง แต่ก็ยังต้องเขียนซ้ำ ๆ และเสี่ยงต่อการพิมพ์ผิดอยู่ดี
พระเอกขี่ม้าขาว: Nullsafe Operator (?->)
ตั้งแต่ PHP 8.0 เป็นต้นมา เราสามารถยุบโค้ดด้านบนทั้งหมดให้เหลือเพียงแค่ บรรทัดเดียว ได้ด้วยการเติมเครื่องหมายคำถาม ? ไว้หน้าลูกศร -> ครับ
ตัวอย่างโค้ดแบบใหม่
PHP
PHP
$country = $user?->getProfile()?->getAddress()?->country;
มันทำงานยังไง?
กลไกของมันเข้าใจง่ายมากครับ PHP จะไล่เช็คจากซ้ายไปขวา
- เช็คว่า
$user เป็น null ไหม? ถ้าใช่ มันจะหยุดทำงานทันทีแล้วคืนค่า null ให้變數 $country
- ถ้า
$user ไม่ใช่ null มันก็จะไปเช็ค $user->getProfile() ต่อ
- ทำแบบนี้ไปเรื่อย ๆ จนสุดสาย
💡 ข้อดี
ถ้าตัวใดตัวหนึ่งในสาย (Chain) เป็น null โค้ดจะไม่พัง (ไม่เกิด Fatal Error) แต่จะส่งกลับเป็น null ทันที เรียกว่าเกิดกระบวนการ Short-circuiting
ความแตกต่างระหว่าง ?-> (Nullsafe) กับ ?? (Null Coalescing)
สองตัวนี้มักจะใช้คู่กัน แต่อย่าสับสนหน้าที่ของมันนะครับ
?-> (Nullsafe)
ใช้เพื่อ “ทางผ่าน” ในการเข้าถึง Property/Method ของ Object อย่างปลอดภัย (ถ้าเจอ null ให้หยุดเดินต่อ)
?? (Null Coalescing)
ใช้เพื่อ “กำหนดค่า Default” ในกรณีที่ผลลัพธ์สุดท้ายเป็น null หรือไม่มีอยู่จริง
การใช้งานร่วมกันแบบทรงพลัง
PHP
PHP
// ถ้าตรงไหนสักแห่งเป็น null ให้ระบุประเทศเป็น 'Unknown' แทน
$country = $user?->getProfile()?->getAddress()?->country ?? 'Unknown';