PlusMagi's Blog By Pitt Phunsanit AI,API,Backend,computer science,Operating Systems,PHP,Programming PHP: First-class Callable Syntax วิธีอ้างอิงฟังก์ชันแบบโมเดิร์น

PHP: First-class Callable Syntax วิธีอ้างอิงฟังก์ชันแบบโมเดิร์น

นับตั้งแต่ PHP 8.1 เป็นต้นมา มีการฟีเจอร์หนึ่งที่ถูกเพิ่มเข้ามาและช่วยเปลี่ยนวิถีการเขียนโค้ดของเราให้สะอาดขึ้นอย่างมาก นั่นคือ First-class Callable Syntax ครับ หากคุณเคยเบื่อกับการที่ต้องส่งชื่อฟังก์ชันเป็น String หรือส่ง Array แปลก ๆ เวลาทำ Callback ฟังก์ชันนี้คือคำตอบครับ


ปัญหาของการอ้างอิงฟังก์ชันแบบเดิม (ก่อน PHP 8.1)

ก่อนหน้านี้เวลาที่เราต้องการนำฟังก์ชันหรือเมธอดไปเป็นอาร์กิวเมนต์ (Callback) ในฟังก์ชันอื่น เช่น array_map หรือ usort เรามักจะใช้วิธีส่งเป็น String หรือ Array ดังนี้ครับ

// 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(...)
$words = ['hello', 'php', 'world'];
// แบบใหม่: ไม่ต้องใส่เครื่องหมายคำพูดอีกต่อไป
$lengths = array_map(strlen(...), $words);

เมธอดของอ็อบเจกต์ (Instance Methods)

  • แบบเดิม
    [$this, 'formatDate']
  • แบบใหม่
    $this->formatDate(...)
class UserRenderer {
    public function format(array $users): array {
        // อ้างอิงเมธอดภายใน Class ตัวเองได้หล่อๆ
        return array_map($this->renderRow(...), $users);
    }

    private function renderRow(User $user): string {
        return "<li>{$user->name}</li>";
    }
}

สแตติกเมธอด (Static Methods)

  • แบบเดิม
    ['Helper', 'generateUuid'] หรือ 'Helper::generateUuid'
  • แบบใหม่
    Helper::generateUuid(...)
$ids = [1, 2, 3];
// IDE รู้ทันทีว่าเรียกใช้ Static Method ตัวไหน
$uuids = array_map(UUIDGenerator::fromId(...), $ids);

ข้อดีที่คุณจะได้รับทันทีที่ย้ายมาใช้

  1. IDE Friendly & Autocomplete
    สิ้นสุดยุคเดาชื่อฟังก์ชันใน String เพราะตอนนี้ IDE (เช่น PHPStorm, VS Code) จะมีระเบิดความสามารถ Autocomplete ขึ้นมาให้ และช่วยเช็กให้ทันทีว่าฟังก์ชันนั้นมีอยู่จริงไหม
  2. ปลอดภัยตอน Refactor
    ถ้าคุณเปลี่ยนชื่อเมธอด ตัว IDE จะไล่เปลี่ยนโค้ดที่ใช้ ... ให้โดยอัตโนมัติ โอกาสเกิด Bug ลดลงมหาศาล
  3. ประสิทธิภาพที่จับต้องได้
    การใช้ ... จะสร้าง Closure ขึ้นมาตั้งแต่ตอนที่คอมไพล์ ซึ่งเร็วกว่าและกินทรัพยากรน้อยกว่าการให้ PHP ไปแกะ String/Array ในตอน Runtime

ข้อควรรู้เพิ่มเติม

[!NOTE] ฟีเจอร์นี้ไม่สามารถใช้ร่วมกับ ตรรกะการเรียกแบบ Dynamic ที่ระบุชื่อฟังก์ชันในตัวแปรตรง ๆ ได้ เช่น $func(...) (ถ้า $func เป็น string) แต่คุณสามารถเลี่ยงไปใช้ Closure::fromCallable($func) แทนได้หากจำเป็นจริง ๆ


สรุป

First-class Callable Syntax (...) เป็นการยกระดับภาษา PHP ให้มีความเป็น Modern Language มากขึ้น มันช่วยปิดช่องโหว่เรื่องความผิดพลาดจากการพิมพ์ String ผิด และทำให้เครื่องมือพัฒนาทำงานได้อย่างเต็มประสิทธิภาพ

ถ้าโปรเจกต์ของคุณรันบน PHP 8.1 ขึ้นไป แล้วล่ะก็ แนะนำให้เริ่มเปลี่ยนมาใช้รูปแบบนี้แทน String หรือ Array Callback ได้เลยครับ โค้ดสะอาดขึ้นแน่นอน!


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

Exit mobile version