ป้ายกำกับ: Strict

PHP: Scalar Type Hinting ของ FunctionPHP: Scalar Type Hinting ของ Function

ในยุคก่อนหน้านี้ PHP ขึ้นชื่อว่าเป็นภาษาแบบ Dynamically Typed หรือภาษาที่ไม่มีการผูกมัดประเภทของข้อมูลอย่างเข้มงวด นักพัฒนาสามารถส่งค่าอะไรก็ได้เข้าไปในฟังก์ชัน ซึ่งแม้จะให้ความยืดหยุ่นสูง แต่ก็มักนำมาซึ่งบั๊กซ่อนแอบที่หาตัวจับได้ยากในโปรเจกต์ขนาดใหญ่

จนกระทั่งการมาถึงของ PHP 7 ระบบได้เปิดตัว Scalar Type Hinting อย่างเป็นทางการ และถูกพัฒนาให้ยอดเยี่ยมยิ่งขึ้นใน PHP 8 ช่วยให้เราสามารถระบุประเภทข้อมูล (Type) ให้กับทั้งโปรแกรมพารามิเตอร์ (Argument) และค่าที่ส่งกลับคืนมา (Return Value) ได้อย่างชัดเจน


ทำไมต้องระบุ Type Hinting?

  1. ลดบั๊กและข้อผิดพลาด (Bug Reduction): ป้องกันไม่ให้ส่งข้อมูลผิดประเภทเข้าฟังก์ชัน เช่น การนำสตริงไปคำนวณทางคณิตศาสตร์
  2. โค้ดอ่านง่ายขึ้น (Readability): นักพัฒนาคนอื่น (หรือตัวคุณเองในอีก 3 เดือนข้างหน้า) สามารถดูจาก Signature ของฟังก์ชันแล้วรู้ได้ทันทีว่าฟังก์ชันนี้ต้องการอะไร และจะส่งอะไรกลับมา
  3. IDE ทำงานได้ฉลาดขึ้น (Better Tooling): IDE อย่าง VS Code หรือ PHPStorm จะสามารถทำ Auto-complete และแจ้งเตือน Error ได้ตั้งแต่ตอนที่คุณกำลังพิมพ์โค้ด

Argument Type Hinting (การระบุ Type ให้พารามิเตอร์)

เราสามารถระบุ Type ไว้ข้างหน้าชื่อตัวแปรในฟังก์ชันได้ทันที โดย Scalar Types พื้นฐานที่รองรับมีดังนี้

  • bool (จริง/เท็จ)
  • float (ทศนิยม)
  • int (จำนวนเต็ม)
  • string (ข้อความ)

ตัวอย่างโค้ด

<?php

function calculateTotal(int $price, int $quantity): int {
    return $price * $quantity;
}

// การใช้งานปกติ
echo calculateTotal(100, 3); // ผลลัพธ์: 300

Return Type Hinting (การระบุ Type ให้ค่าที่ส่งกลับ)

เราสามารถกำหนดได้ว่าฟังก์ชันนี้ “ต้อง” Return ค่ากลับมาเป็นข้อมูลประเภทไหน โดยใช้เครื่องหมายโคลอน : ตามด้วยประเภทข้อมูล ไว้หลังวงเล็บของฟังก์ชัน

<?php

function isAdult(int $age): bool {
    return $age >= 18;
}

// ถ้ารันฟังก์ชันนี้ จะได้ค่าเป็น true หรือ false เสมอ
var_dump(isAdult(20)); // bool(true)

นอกจาก Scalar Types ทั่วไปแล้ว ยังมี Return Type พิเศษที่น่าสนใจ เช่น

  • : void — ใช้เมื่อฟังก์ชันนั้นไม่มีการส่งค่ากลับ (ไม่มี return หรือมีแค่ return; เปล่า ๆ)
  • : never — (เพิ่มเข้ามาใน PHP 8.1) สำหรับฟังก์ชันที่ไม่มีวันทำงานเสร็จสมบูรณ์ เช่น ฟังก์ชันที่ทำหน้าที่ exit() หรือ throw exception เสมอ

โหมดการทำงาน: Coercive vs Strict Mode

นี่คือจุดที่สำคัญที่สุดของ PHP การทำงานของ Type Hinting จะขึ้นอยู่กับว่าคุณเปิด Strict Mode หรือไม่


โหมดปกติ (Coercive Mode – ค่าเริ่มต้น)

PHP จะพยายามแปลงประเภทข้อมูลให้โดยอัตโนมัติ (Type Coercion) หากข้อมูลนั้นพอจะแปลงได้ เช่น ถ้าฟังก์ชันรับ int แต่คุณส่งสตริง "5" เข้าไป PHP จะแปลงเป็นเลข 5 ให้ทันทีโดยไม่แจ้ง Error

<?php
function printNumber(int $num) {
    echo $num;
}

printNumber("10"); // ผลลัพธ์: 10 (PHP แปลงจาก string เป็น int ให้ใจดีสุดๆ)

โหมดเข้มงวด (Strict Mode – แนะนำ)

หากคุณต้องการความปลอดภัยสูงสุด คุณต้องเปิดใช้งาน Strict Mode โดยการใส่ตรรกะไว้ที่ บรรทัดแรกสุด ของไฟล์โค้ด (ก่อนโค้ดอื่น ๆ ทั้งหมด) ดังนี้

<?php
declare(strict_types=1); // เปิดใช้งาน Strict Mode

function printNumber(int $num) {
    echo $num;
}

printNumber("10"); 
// ผลลัพธ์: Fatal error: Uncaught TypeError: printNumber(): Argument #1 ($num) must be of type int, string given

ข้อควรระวัง: declare(strict_types=1); จะมีผลเฉพาะภายในไฟล์ที่ระบุไว้เท่านั้น ไม่ส่งผลข้ามไปยังไฟล์อื่นที่ทำ include หรือ require เข้ามา


การต่อยอดใน PHP 8: Union Types และ Mixed Type

ในชีวิตจริง ข้อมูลบางอย่างอาจเป็นไปได้มากกว่าหนึ่งประเภท PHP 8 จึงได้เพิ่มฟีเจอร์เพื่อตอบโจทย์นี้


Union Types (|)

ระบุว่าตัวแปรสามารถเป็น Type ใด Type หนึ่งในกลุ่มที่กำหนดได้ เช่น เป็นได้ทั้ง float หรือ int

<?php
declare(strict_types=1);

// รับได้ทั้ง int และ float และรีเทิร์นได้ทั้ง int และ float
function square(int|float $number): int|float {
    return $number * $number;
}

Mixed Type (mixed)

หากตัวแปรนั้นสามารถเป็นอะไรก็ได้จริงๆ (คล้ายกับไม่ใส่ Type ในสมัยก่อน) แต่การใส่ mixed จะช่วยบอกให้เพื่อนร่วมทีมรู้ว่า “เราตั้งใจให้มันเป็นอะไรก็ได้นะ ไม่ใช่ว่าลืมใส่”

<?php
function debugLog(mixed $data): void {
    print_r($data);
}

สรุป

การใช้งาน Scalar Type Hinting ควบคู่กับการเปิด declare(strict_types=1); ถือเป็น Best Practice ของการเขียน PHP ในปัจจุบัน มันเปลี่ยนโฉมหน้าของภาษา PHP จากภาษาที่เคยถูกมองว่า “เขียนง่ายแต่พังง่าย” ให้กลายเป็นภาษาที่มีโครงสร้างแข็งแรง ปลอดภัย และเหมาะกับการพัฒนาระบบระดับ Enterprise ได้อย่างมั่นใจ


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