ป้ายกำกับ: Intelephense

PHP: Never Type สำหรับฟังก์ชันที่ไม่มีการ Return (เช่น redirect หรือ exit)PHP: Never Type สำหรับฟังก์ชันที่ไม่มีการ Return (เช่น redirect หรือ exit)

ในการเขียนโปรแกรมด้วย PHP ยุคใหม่ (ตั้งแต่ PHP 8.1 เป็นต้นไป) มีฟีเจอร์หนึ่งที่ช่วยให้โค้ดของเรามีความชัดเจน แม่นยำ และปลอดภัยมากขึ้น นั่นคือการกำหนด Type Hinting แบบ never type บทความนี้จะพาไปทำความเข้าใจว่า never type คืออะไร แตกต่างจาก void อย่างไร และจะนำไปประยุกต์ใช้กับฟังก์ชันที่ไม่มีวัน Return (เช่นการทำ Redirect หรือสั่ง Exit) ได้อย่างไรครับ


never type คืออะไร?

never คือ Return Type ที่ใช้ระบุว่า “ฟังก์ชันนี้จะไม่มีวันส่งค่ากลับมาและสิ้นสุดการทำงานแบบปกติได้เลย” เมื่อเรากำหนดให้ฟังก์ชันส่งค่ากลับเป็น never ฟังก์ชันนั้นจะต้องเกิดเหตุการณ์อย่างใดอย่างหนึ่งใน 2 กรณีนี้เท่านั้น

  1. มีการเรียกใช้คำสั่ง exit() หรือ die() เพื่อหยุดการทำงานของสคริปต์ทันที
  2. มีการโยน Exception (throw Exception) ออกไป

ข้อสังเกต: ถ้าเราประกาศฟังก์ชันเป็น never แต่ภายในดันทะลึ่งมีคำสั่ง return หรือปล่อยให้ฟังก์ชันทำงานจนจบ Block {} ตามปกติ PHP จะพ่นข้อผิดพลาด TypeError ออกมาทันที


ความแตกต่างระหว่าง void กับ never

หลายคนมักจะสับสนระหว่างสองตัวนี้ เพราะดูเหมือนเป็นการ “ไม่คืนค่า” เหมือนกัน แต่ในทางทฤษฎีและปฏิบัติ มันต่างกันโดยสิ้นเชิงครับ

คุณสมบัติvoidnever
ความหมายทำงานเสร็จแล้ว ไม่ส่งค่าอะไรกลับมาฟังก์ชันนี้ ไม่มีวันทำงานเสร็จสิ้นแบบปกติ
การควบคุมโปรแกรมจะทำงานในบรรทัดถัดไปต่อโปรแกรมที่เรียกใช้จะหยุดลง หรือกระโดดไปที่ Catch Block
ตัวอย่างการใช้ฟังก์ชันเซ็ตค่า (Setter), ฟังก์ชันบันทึก Logฟังก์ชัน Redirect, ฟังก์ชันหยุดการทำงาน

การประยุกต์ใช้งานในชีวิตจริง

ลองมาดูตัวอย่างยอดฮิตที่เรามักจะได้ใช้ never กันบ่อย ๆ ครับ


ฟังก์ชันสำหรับการ Redirect (HTTP Redirection)

ในระบบ Web Application หลังจากที่เราสั่ง header('Location: ...') แล้ว เรามักจะต้องสั่ง exit() ควบคู่ไปด้วยเสมอเพื่อป้องกันไม่ให้ Script ด้านล่างทำงานต่อ

<?php

// ประกาศฟังก์ชันด้วยระบบเนเวอร์รรร!
function redirectToLogin(): never 
{
    header('Location: /login.php');
    exit(); // สิ้นสุดการทำงานตรงนี้ ไม่มีทางรันไปถึงบรรทัดอื่น
}

// การใช้งาน
if (!isLoggedIn()) {
    redirectToLogin();
    
    // Static Analysis Tool (เช่น PHPStan) จะรู้ทันทีว่าโค้ดตรงนี้ไม่มีวันถูกรัน
    echo "โค้ดตรงนี้จะไม่มีวันถูกประมวลผล"; 
}

ฟังก์ชัน Custom Helper สำหรับการจัดการ Error หรือ Debug

เวลาเราสร้างฟังก์ชันจำพวก dd() (Dump and Die) แบบใน Laravel หรือฟังก์ชันจัดการ API Error Response

<?php

function sendJsonError(string $message, int $code = 400): never 
{
    header('Content-Type: application/json');
    http_response_code($code);
    echo json_encode(['error' => $message]);
    exit(); 
}

// การใช้งาน
if (empty($_POST['username'])) {
    sendJsonError('Username is required');
}

// ปลอดภัยหายห่วง เพราะถ้า Username ว่าง มันจะหยุดตั้งแต่ฟังก์ชันข้างบนแล้ว
$username = $_POST['username'];

ประโยชน์ที่คุณจะได้รับเมื่อใช้ never

  1. Static Analysis รักคุณ: เครื่องมืออย่าง PHPStan, Psalm หรือแม้แต่ Intelephense ใน VS Code จะเข้าใจทันทีว่าหลังจากบรรทัดที่เรียกฟังก์ชันนี้ โดเมนของโค้ดจะถูกตัดขาด (Dead Code) ทำให้มันช่วยเตือนเราได้แม่นยำขึ้นหากเราเผลอเขียนโค้ดที่ไม่มีวันถูกเรียกใช้งาน
  2. สื่อสารกับทีมได้ชัดเจน (Self-Documenting): ทันทีที่เพื่อนในทีม (หรือตัวเราเองในอีก 3 เดือนข้างหน้า) มาอ่านโค้ด จะเข้าใจได้ทันทีว่า “อ๋อ ฟังก์ชันนี้เรียกแล้วจบเลยนะ ไม่ต้องเขียน Logic มารองรับหลังจากนี้”
  3. ลดบั๊กที่เกิดจากการลืม exit: บ่อยครั้งที่เราเขียน header('Location: ...') แล้วลืมใส่ exit; ทำให้สคริปต์แอบทำงานต่อจนเกิดช่องโหว่ความปลอดภัย การครอบมันด้วยฟังก์ชันที่เป็น never จะบังคับให้เราต้องเขียนโค้ดให้ถูกต้องตามเงื่อนไขเสมอ

สรุป

never type เป็นหนึ่งในฟีเจอร์เล็กๆ ที่ช่วยยกระดับ Type System ของ PHP ให้แข็งแกร่งขึ้น หากคุณกำลังเขียน PHP 8.1+ และมีฟังก์ชันประเภทที่ทำหน้าที่ตัดจบการทำงาน เช่น Redirect, Exit, หรือ Throw Exception อย่าลืมเปลี่ยนมาใช้ : never แทน : void เพื่อโค้ดที่คลีนและปลอดภัยขึ้นกันครับ!


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