การโยน Exception ด้วย throw
จากบทที่แล้ว เราได้เรียนรู้การใช้ try-catch เพื่อดักจับและจัดการกับ Exception ที่อาจเกิดขึ้นในโปรแกรมของเรา แต่ในบางครั้ง เราอาจต้องการ *สร้าง* Exception ขึ้นมาเองเมื่อเงื่อนไขบางอย่างไม่เป็นไปตามที่เราคาดหวัง นั่นคือหน้าที่ของคำสั่ง throw
throw Keyword คืออะไร?
throw เป็น keyword ในภาษา PHP ที่ใช้สำหรับ "โยน" (throw) Exception ออกไป ซึ่งหมายความว่าเรากำลังบอกให้โปรแกรมรู้ว่า "เกิดข้อผิดพลาดขึ้นแล้วนะ!" และให้ไปจัดการกับข้อผิดพลาดนั้นในส่วนของ catch block ที่เหมาะสม
Exception Object คืออะไร?
เมื่อเรา throw Exception เราไม่ได้โยนแค่ "ข้อผิดพลาด" เฉยๆ แต่เรากำลังโยน *object* ที่เป็น instance ของ class ที่สืบทอดมาจาก Exception class (หรือ class Exception เองก็ได้) Object นี้จะเก็บข้อมูลเกี่ยวกับข้อผิดพลาดที่เกิดขึ้น เช่น ข้อความอธิบาย, รหัสข้อผิดพลาด (error code), และ stack trace (ลำดับการเรียกใช้ฟังก์ชันจนเกิดข้อผิดพลาด)
รูปแบบการใช้งาน throw
รูปแบบการใช้งาน throw ง่ายมาก:
throw new Exception("ข้อความอธิบายข้อผิดพลาด");
หรือ:
throw new Exception("ข้อความอธิบายข้อผิดพลาด", รหัสข้อผิดพลาด);
โดยที่:
new Exception("..."): คือการสร้าง instance ใหม่ของ classExceptionโดยส่งข้อความอธิบายข้อผิดพลาด (message) และรหัสข้อผิดพลาด (code) เป็น arguments ให้กับ constructor"ข้อความอธิบายข้อผิดพลาด": คือข้อความที่อธิบายว่าเกิดข้อผิดพลาดอะไรขึ้น ควรเขียนให้เข้าใจง่ายและสื่อความหมายรหัสข้อผิดพลาด: คือตัวเลขที่ใช้ระบุประเภทของข้อผิดพลาด (optional)
ตัวอย่างการใช้งาน throw
ลองดูตัวอย่างง่ายๆ ที่เราจะ throw Exception ถ้าตัวเลขที่รับเข้ามาเป็นลบ:
function หารเลข(int $ตัวตั้ง, int $ตัวหาร): float {
if ($ตัวหาร == 0) {
throw new Exception("ไม่สามารถหารด้วยศูนย์ได้");
}
if ($ตัวตั้ง < 0 || $ตัวหาร < 0) {
throw new Exception("ตัวเลขต้องไม่เป็นลบ", 100); // รหัสข้อผิดพลาด 100
}
return $ตัวตั้ง / $ตัวหาร;
}
try {
$ผลลัพธ์ = หารเลข(10, -2);
echo "ผลลัพธ์คือ: " . $ผลลัพธ์;
} catch (Exception $e) {
echo "เกิดข้อผิดพลาด: " . $e->getMessage() . "<br>";
echo "รหัสข้อผิดพลาด: " . $e->getCode() . "<br>"; // แสดงรหัสข้อผิดพลาด
}
ในตัวอย่างนี้:
- ฟังก์ชัน
หารเลข()จะตรวจสอบว่าตัวหารเป็น 0 หรือไม่ และตัวตั้งหรือตัวหารเป็นค่าลบหรือไม่ - ถ้าตัวหารเป็น 0 หรือตัวตั้งหรือตัวหารเป็นค่าลบ จะ
throwException ออกไปพร้อมข้อความอธิบาย - ใน
tryblock เราเรียกใช้ฟังก์ชันหารเลข() - ถ้าเกิด Exception ขึ้นใน
tryblockcatchblock จะถูกเรียกใช้งาน - ใน
catchblock เราจะแสดงข้อความอธิบายข้อผิดพลาดและรหัสข้อผิดพลาด (ถ้ามี) ที่ได้จาก Exception object
เมื่อรันโค้ดนี้ จะได้ผลลัพธ์:
เกิดข้อผิดพลาด: ตัวเลขต้องไม่เป็นลบ
รหัสข้อผิดพลาด: 100
การจัดการ Exception ที่ถูก throw
เมื่อเรา throw Exception สิ่งสำคัญคือต้องมี catch block ที่เหมาะสมเพื่อจัดการกับ Exception นั้น หากไม่มี catch block ที่ตรงกับประเภทของ Exception ที่ถูก throw โปรแกรมจะหยุดทำงานและแสดงข้อผิดพลาด (uncaught exception) ดังนั้นควรตรวจสอบให้แน่ใจว่า Exception ทุกประเภทที่เรา throw สามารถถูก catch ได้อย่างถูกต้อง
ตัวอย่างเช่น หากเราต้องการจัดการกับ Exception ที่เกิดจากการหารด้วยศูนย์แยกต่างหาก เราสามารถเพิ่ม catch block อีกอันได้:
function หารเลข(int $ตัวตั้ง, int $ตัวหาร): float {
if ($ตัวหาร == 0) {
throw new Exception("ไม่สามารถหารด้วยศูนย์ได้");
}
if ($ตัวตั้ง < 0 || $ตัวหาร < 0) {
throw new Exception("ตัวเลขต้องไม่เป็นลบ", 100); // รหัสข้อผิดพลาด 100
}
return $ตัวตั้ง / $ตัวหาร;
}
try {
$ผลลัพธ์ = หารเลข(10, 0);
echo "ผลลัพธ์คือ: " . $ผลลัพธ์;
} catch (DivisionByZeroError $e) {
echo "เกิดข้อผิดพลาด (DivisionByZeroError): " . $e->getMessage() . "<br>";
}
catch (Exception $e) {
echo "เกิดข้อผิดพลาด: " . $e->getMessage() . "<br>";
echo "รหัสข้อผิดพลาด: " . $e->getCode() . "<br>"; // แสดงรหัสข้อผิดพลาด
}
ในตัวอย่างนี้ เราได้เพิ่ม catch (DivisionByZeroError $e) เพื่อจัดการกับ Exception ที่เกิดจากการหารด้วยศูนย์โดยเฉพาะ (ใน PHP 8 เป็นต้นไป การหารด้วยศูนย์จะ throw `DivisionByZeroError` ไม่ใช่ `Exception` ธรรมดา) ถ้า Exception ที่ถูก throw ไม่ใช่ DivisionByZeroError catch (Exception $e) จะถูกเรียกใช้งานแทน
**ข้อควรจำ:** ลำดับของ catch blocks มีความสำคัญ catch blocks ที่เฉพาะเจาะจงกว่า ควรอยู่ก่อน catch blocks ที่ทั่วไปกว่า
สรุป
การใช้ throw เป็นเครื่องมือสำคัญในการจัดการข้อผิดพลาดใน PHP ช่วยให้เราสามารถสร้าง Exception ขึ้นมาเองเมื่อเกิดเงื่อนไขที่ไม่คาดฝัน และส่งต่อการจัดการข้อผิดพลาดไปยัง catch block ที่เหมาะสม การใช้ throw อย่างถูกต้องจะช่วยให้โค้ดของเรามีความแข็งแกร่งและง่ายต่อการบำรุงรักษามากยิ่งขึ้น ในบทต่อไป เราจะเรียนรู้การสร้าง Custom Exception เพื่อให้ Exception ของเรามีความหมายและสามารถจัดการได้ดียิ่งขึ้น