PHP: First-class Callable Syntax วิธีอ้างอิงฟังก์ชันแบบโมเดิร์น
นับตั้งแต่ PHP 8.1 เป็นต้นมา มีการฟีเจอร์หนึ่งที่ถูกเพิ่มเข้ามาและช่วยเปลี่ยนวิถีการเขียนโค้ดของเราให้สะอาดขึ้นอย่างมาก นั่นคือ First-class Callable Syntax ครับ หากคุณเคยเบื่อกับการที่ต้องส่งชื่อฟังก์ชันเป็น String หรือส่ง Array แปลก ๆ เวลาทำ Callback ฟังก์ชันนี้คือคำตอบครับ
ปัญหาของการอ้างอิงฟังก์ชันแบบเดิม (ก่อน PHP 8.1)
ก่อนหน้านี้เวลาที่เราต้องการนำฟังก์ชันหรือเมธอดไปเป็นอาร์กิวเมนต์ (Callback) ในฟังก์ชันอื่น เช่น array_map หรือ usort เรามักจะใช้วิธีส่งเป็น String หรือ Array ดังนี้ครับ
PHP
PHP
// 1. อ้างอิงฟังก์ชันทั่วไปด้วย String
$lengths = array_map('strlen', ['apple', 'banana']);
// 2. อ้างอิง Method ของ Object ด้วย Array [$object, 'method']
$processor = new DataProcessor();
$result = array_map([$processor, 'cleanData'], $dirtyData);
// 3. อ้างอิง Static Method ด้วย String "Class::method" หรือ Array
$slugs = array_map('StringHelper::slugify', $titles);
ทำไมวิธีเดิมถึงมีปัญหา?
- ไม่มี Type Safety
IDE ไม่รู้ว่า String หรือ Array นั้นคือฟังก์ชันจริง ๆ หรือเปล่า จนกว่าโค้ดจะรัน (Runtime)
- หา Bug ยาก
ถ้าคุณพิมพ์ชื่อฟังก์ชันผิดใน String (เช่น 'str_len' แทน 'strlen') IDE จะไม่แจ้งเตือน (No Static Analysis support)
- Refactor ลำบาก
เวลาจะเปลี่ยนชื่อ Method ด้วยเครื่องมือใน IDE ชื่อใน String มักจะไม่ถูกเปลี่ยนตามไปด้วย
พระเอกมาแล้ว: First-class Callable Syntax คืออะไร?
ใน PHP 8.1 ได้นำรูปแบบการเขียนแบบใหม่มาใช้ โดยการใช้เครื่องหมาย ... (Ellipsis) ต่อท้ายชื่อฟังก์ชันหรือเมธอดที่เราต้องการอ้างอิง ระบบจะทำการสร้าง Closure (หรืออ็อบเจกต์ที่เรียกใช้งานได้) ขึ้นมาให้เราทันที โดยที่เราไม่ต้องครอบด้วย String อีกต่อไป
รูปแบบโครงสร้าง (Syntax)
ฟังก์ชันที่ต้องการ(…)
เปรียบเทียบการใช้งาน: อดีต VS ปัจจุบัน
ลองมาดูกันครับว่าเมื่อเปลี่ยนมาใช้ First-class Callable Syntax แล้ว โดคจะดูดีขึ้นขนาดไหน
ฟังก์ชันทั่วไป (Standard Functions)
- แบบเดิม
'strlen'
- แบบใหม่
strlen(...)
PHP
PHP
$words = ['hello', 'php', 'world'];
// แบบใหม่: ไม่ต้องใส่เครื่องหมายคำพูดอีกต่อไป
$lengths = array_map(strlen(...), $words);