การสร้าง Custom Exception
ในบทที่แล้ว เราได้เรียนรู้เกี่ยวกับการโยน Exception ด้วย `throw` และการดักจับ Exception ด้วย `try-catch` แต่บางครั้ง Exception ที่ PHP มีให้อาจไม่ครอบคลุมความต้องการของเราทั้งหมด ในสถานการณ์เช่นนี้ เราสามารถสร้าง Custom Exception หรือ Exception ที่เรากำหนดขึ้นเองได้ เพื่อให้สื่อความหมายของข้อผิดพลาดได้ชัดเจนยิ่งขึ้น
ทำไมต้องสร้าง Custom Exception?
- ความชัดเจน: Custom Exception ช่วยให้เราระบุประเภทของข้อผิดพลาดได้อย่างแม่นยำ ทำให้ debugging และการจัดการข้อผิดพลาดง่ายขึ้น
- การจัดการที่เฉพาะเจาะจง: เราสามารถเขียน `catch` block ที่จัดการกับ Custom Exception ของเราโดยเฉพาะ ทำให้เราสามารถจัดการกับข้อผิดพลาดแต่ละประเภทได้อย่างเหมาะสม
- การเพิ่มข้อมูล: เราสามารถเพิ่ม properties และ methods ที่เฉพาะเจาะจงให้กับ Custom Exception ของเรา เพื่อให้ข้อมูลเพิ่มเติมเกี่ยวกับข้อผิดพลาด
การสร้าง Custom Exception: extends Exception
การสร้าง Custom Exception ใน PHP ทำได้ง่ายมาก เพียงแค่สร้าง class ใหม่ที่ `extends` มาจาก class `Exception` หรือ class อื่นที่ `extends` มาจาก `Exception` (เช่น `RuntimeException`, `InvalidArgumentException`) การ `extends` หมายถึงการสืบทอดคุณสมบัติและ methods จาก class แม่ (parent class) ซึ่งในที่นี้คือ `Exception`
ตัวอย่างเช่น หากเราต้องการสร้าง Exception สำหรับกรณีที่ข้อมูลไม่ถูกต้อง เราสามารถสร้าง class ที่ชื่อ `InvalidDataException` ได้ดังนี้:
class InvalidDataException extends Exception {
// ...
}
เพียงเท่านี้ เราก็มี Custom Exception ที่สามารถนำไปใช้งานได้แล้ว
Properties ใน Custom Exception
เราสามารถเพิ่ม properties ให้กับ Custom Exception ของเราได้ เพื่อเก็บข้อมูลเพิ่มเติมเกี่ยวกับข้อผิดพลาด เช่น รหัสข้อผิดพลาด, ชื่อ field ที่เกิดข้อผิดพลาด หรือข้อมูลอื่นๆ ที่เกี่ยวข้อง
ตัวอย่างเช่น หากเราต้องการเก็บรหัสข้อผิดพลาดและชื่อ field ที่เกิดข้อผิดพลาดใน `InvalidDataException` เราสามารถทำได้ดังนี้:
class InvalidDataException extends Exception {
protected $errorCode;
protected $fieldName;
public function __construct($message = "", $code = 0, $fieldName = "", Throwable $previous = null) {
parent::__construct($message, $code, $previous);
$this->errorCode = $code; // ใช้ $code จาก constructor เป็น errorCode
$this->fieldName = $fieldName;
}
public function getErrorCode() {
return $this->errorCode;
}
public function getFieldName() {
return $this->fieldName;
}
}
ในตัวอย่างนี้ เราได้เพิ่ม properties $errorCode และ $fieldName และ constructor ที่รับค่าเหล่านี้เข้ามา นอกจากนี้ เรายังสร้าง getter methods (`getErrorCode` และ `getFieldName`) เพื่อให้สามารถเข้าถึงค่าเหล่านี้จากภายนอก class ได้
อธิบายเพิ่มเติม:
protected: เป็น access modifier ที่กำหนดว่า properties และ methods สามารถเข้าถึงได้จากภายใน class เอง และ class ที่สืบทอด (extended class) เท่านั้น__construct: เป็น magic method ที่เรียกว่า constructor ซึ่งจะถูกเรียกเมื่อสร้าง object ใหม่จาก class นี้parent::__construct($message, $code, $previous): เป็นการเรียก constructor ของ class แม่ (Exception) เพื่อกำหนดค่า message, code และ previous exceptionThrowable $previous = null: เป็นการกำหนด type hint ว่า argument `$previous` จะต้องเป็น object ที่ implement interface `Throwable` (ซึ่ง Exception ก็ implement interface นี้) และกำหนดค่า default เป็น `null`
Methods ใน Custom Exception
นอกจาก properties แล้ว เรายังสามารถเพิ่ม methods ให้กับ Custom Exception ของเราได้ เพื่อให้สามารถดำเนินการบางอย่างที่เกี่ยวข้องกับข้อผิดพลาดได้ เช่น การ format ข้อความ error หรือการบันทึก log
ตัวอย่างเช่น หากเราต้องการสร้าง method ที่ format ข้อความ error ให้เป็นรูปแบบที่อ่านง่าย เราสามารถทำได้ดังนี้:
class InvalidDataException extends Exception {
protected $errorCode;
protected $fieldName;
public function __construct($message = "", $code = 0, $fieldName = "", Throwable $previous = null) {
parent::__construct($message, $code, $previous);
$this->errorCode = $code;
$this->fieldName = $fieldName;
}
public function getErrorCode() {
return $this->errorCode;
}
public function getFieldName() {
return $this->fieldName;
}
public function formatErrorMessage() {
return "Error Code: " . $this->errorCode . ", Field: " . $this->fieldName . ", Message: " . $this->getMessage();
}
}
ในตัวอย่างนี้ เราได้เพิ่ม method formatErrorMessage ซึ่งจะ return ข้อความ error ที่ format แล้ว โดยรวมข้อมูลจาก properties ต่างๆ เข้าด้วยกัน
ตัวอย่างการใช้งาน Custom Exception
เมื่อเราสร้าง Custom Exception แล้ว เราสามารถนำไปใช้งานได้เหมือนกับ Exception ทั่วไป โดยการ `throw` เมื่อเกิดข้อผิดพลาด และ `catch` ใน `try-catch` block
function validateData($data) {
if (empty($data['name'])) {
throw new InvalidDataException("Name is required", 1001, 'name');
}
if (!is_numeric($data['age'])) {
throw new InvalidDataException("Age must be a number", 1002, 'age');
}
return true;
}
try {
$data = [
'name' => '',
'age' => 'abc'
];
validateData($data);
echo "Data is valid!";
} catch (InvalidDataException $e) {
echo "Error: " . $e->formatErrorMessage();
} catch (Exception $e) {
echo "An unexpected error occurred: " . $e->getMessage();
}
ในตัวอย่างนี้ เราได้สร้าง function validateData ซึ่งจะตรวจสอบข้อมูล หากข้อมูลไม่ถูกต้อง จะ `throw` `InvalidDataException` พร้อมกับ message, error code และ field name ที่เกี่ยวข้อง ใน `try-catch` block เราจะ `catch` `InvalidDataException` และเรียกใช้ method formatErrorMessage เพื่อแสดงข้อความ error ที่ format แล้ว หากเกิด Exception อื่นๆ ที่ไม่ใช่ `InvalidDataException` เราจะ `catch` `Exception` และแสดงข้อความ error ทั่วไป
ข้อสังเกต:
- การ `catch` `InvalidDataException` ก่อน `Exception` เป็นสิ่งสำคัญ เพราะถ้าเรา `catch` `Exception` ก่อน `InvalidDataException` จะไม่มีโอกาสถูก `catch` เลย เนื่องจาก `InvalidDataException` ก็เป็น `Exception` เช่นกัน
- การกำหนด error code ที่แตกต่างกันสำหรับแต่ละประเภทของข้อผิดพลาด จะช่วยให้เราสามารถจัดการกับข้อผิดพลาดแต่ละประเภทได้อย่างละเอียดมากขึ้น
สรุป
การสร้าง Custom Exception เป็นเทคนิคที่มีประโยชน์ในการจัดการข้อผิดพลาดใน PHP ช่วยให้เราสามารถระบุประเภทของข้อผิดพลาดได้อย่างแม่นยำ และจัดการกับข้อผิดพลาดแต่ละประเภทได้อย่างเหมาะสม โดยการสร้าง class ที่ `extends` มาจาก `Exception` และเพิ่ม properties และ methods ที่เฉพาะเจาะจง
ในบทถัดไป เราจะเรียนรู้เกี่ยวกับการใช้งาน Exception ที่เราสร้างขึ้นเองในสถานการณ์ต่างๆ