การจัดการ Error ที่ไม่ได้ถูก Handle
ในบทก่อนหน้า เราได้พูดถึงการจัดการ Exception ที่ไม่ได้ถูก `catch` ซึ่งเป็นหนึ่งในกลไกสำคัญในการจัดการข้อผิดพลาดใน PHP แต่ยังมีอีกประเภทของข้อผิดพลาดที่อาจเกิดขึ้นได้ และไม่ได้อยู่ในรูปแบบของ Exception นั่นคือ Error ทั่วไป เช่น Warning, Notice, และ Strict Standards ซึ่ง PHP จะส่งออกมาเมื่อพบปัญหาต่างๆ ในโค้ดของเรา การจัดการ Error เหล่านี้ก็มีความสำคัญไม่แพ้กัน เพื่อให้โปรแกรมของเราทำงานได้อย่างราบรื่นและให้ข้อมูลที่เป็นประโยชน์เมื่อเกิดข้อผิดพลาด
Global Error Handler
PHP มีฟังก์ชัน `set_error_handler()` ที่ช่วยให้เราสามารถกำหนดฟังก์ชันที่จะถูกเรียกใช้เมื่อเกิด Error ขึ้นในโปรแกรมของเรา ฟังก์ชันนี้เรียกว่า Global Error Handler และเป็นเครื่องมือที่มีประโยชน์อย่างมากในการจัดการ Error ที่ไม่ได้ถูก Handle โดยปกติ
รูปแบบการใช้งานของ `set_error_handler()` คือ:
set_error_handler(callable $error_handler, int $error_types = E_ALL): ?callable
- `$error_handler`: เป็นฟังก์ชัน (callable) ที่จะถูกเรียกเมื่อเกิด Error ฟังก์ชันนี้จะต้องรับพารามิเตอร์อย่างน้อย 2 ตัว คือ error level และ error message
- `$error_types`: เป็น optional parameter ที่ระบุประเภทของ Error ที่เราต้องการให้ Error Handler นี้จัดการ ถ้าไม่ระบุ จะจัดการ Error ทุกประเภท (E_ALL)
ตัวอย่างการใช้งาน:
<?php
function errorHandler(int $errno, string $errstr, string $errfile, int $errline): bool
{
echo "<b>Error:</b> [$errno] $errstr<br>";
echo " Error on line $errline in $errfile<br>";
return true; // Prevent the default PHP error handler from running
}
// Set error handler
set_error_handler("errorHandler");
// Trigger an error
$test = 1;
if ($test > 2) {
echo "Test is greater than 2";
} else {
trigger_error("Value must be greater than 2", E_USER_WARNING);
}
?>
ในตัวอย่างนี้ เราได้สร้างฟังก์ชัน `errorHandler()` เพื่อจัดการ Error และใช้ `set_error_handler()` เพื่อกำหนดให้ฟังก์ชันนี้เป็น Global Error Handler เมื่อเกิด Error ขึ้นในโปรแกรม (ในที่นี้คือการใช้ `trigger_error()` เพื่อสร้าง Error ประเภท E_USER_WARNING) ฟังก์ชัน `errorHandler()` จะถูกเรียกและแสดงข้อมูล Error ออกมา
ข้อควรระวัง: การ return `true` จาก Error Handler จะป้องกันไม่ให้ PHP default error handler ทำงาน ซึ่งหมายความว่า Error จะไม่ถูกแสดงผลในหน้าจอ (ถ้าไม่ได้จัดการใน Error Handler เอง) การ return `false` (หรือไม่ return อะไรเลย) จะทำให้ PHP default error handler ทำงานต่อจาก Error Handler ของเรา
การแปลง Error เป็น Exception
บางครั้ง การจัดการ Error ในรูปแบบ Exception อาจจะสะดวกและยืดหยุ่นกว่า โดยเฉพาะอย่างยิ่งเมื่อเราใช้ try-catch block ในการจัดการข้อผิดพลาดอยู่แล้ว เราสามารถแปลง Error เป็น Exception ได้โดยการโยน Exception ใน Error Handler ของเรา
ตัวอย่าง:
<?php
class ErrorException extends Exception {}
function errorHandler(int $errno, string $errstr, string $errfile, int $errline): bool
{
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("errorHandler");
try {
// Trigger an error
$test = 1;
if ($test > 2) {
echo "Test is greater than 2";
} else {
trigger_error("Value must be greater than 2", E_USER_WARNING);
}
} catch (ErrorException $e) {
echo "<b>Caught Error Exception:</b> " . $e->getMessage() . "<br>";
echo " File: " . $e->getFile() . "<br>";
echo " Line: " . $e->getLine() . "<br>";
}
?>
ในตัวอย่างนี้ เราได้สร้าง Custom Exception ชื่อ `ErrorException` และใน Error Handler ของเรา เราได้โยน `ErrorException` เมื่อเกิด Error ขึ้น ทำให้เราสามารถ `catch` Error ในรูปแบบ Exception ได้โดยใช้ try-catch block
ข้อดีของการแปลง Error เป็น Exception:
- ทำให้การจัดการ Error เป็นไปในรูปแบบเดียวกันกับการจัดการ Exception
- สามารถใช้ try-catch block ในการจัดการ Error ได้
- ทำให้โค้ดอ่านง่ายและบำรุงรักษาได้ง่ายขึ้น
การบันทึก Log
ไม่ว่าเราจะจัดการ Error ด้วยวิธีใด สิ่งสำคัญคือต้องบันทึกข้อมูล Error ไว้ เพื่อให้เราสามารถวิเคราะห์และแก้ไขปัญหาได้ในภายหลัง เราสามารถใช้ Monolog (หรือ Logging Library อื่นๆ) ที่เราได้เรียนรู้ในบทก่อนหน้านี้เพื่อบันทึกข้อมูล Error ได้
ตัวอย่าง:
<?php
require_once 'vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
// Create a logger
$log = new Logger('my_app');
$log->pushHandler(new StreamHandler('error.log', Logger::WARNING)); // Log WARNING and above
function errorHandler(int $errno, string $errstr, string $errfile, int $errline): bool
{
global $log;
$log->warning("Error: [$errno] $errstr in $errfile on line $errline");
return true;
}
set_error_handler("errorHandler");
// Trigger an error
$test = 1;
if ($test > 2) {
echo "Test is greater than 2";
} else {
trigger_error("Value must be greater than 2", E_USER_WARNING);
}
?>
ในตัวอย่างนี้ เราได้สร้าง Logger โดยใช้ Monolog และกำหนดให้บันทึก Log ประเภท WARNING ขึ้นไปในไฟล์ `error.log` ใน Error Handler ของเรา เราได้ใช้ `$log->warning()` เพื่อบันทึกข้อมูล Error ลงใน Log ไฟล์
ข้อดีของการบันทึก Log:
- ช่วยให้เราสามารถวิเคราะห์และแก้ไขปัญหาได้ในภายหลัง
- ช่วยให้เราสามารถติดตามการทำงานของโปรแกรมและตรวจจับข้อผิดพลาดที่อาจเกิดขึ้นได้
- ช่วยให้เราสามารถปรับปรุงประสิทธิภาพและความเสถียรของโปรแกรม
ข้อผิดพลาดที่พบบ่อยในการจัดการ Error:
- ไม่ได้กำหนด Error Handler: ทำให้ Error ถูกแสดงผลในหน้าจอ ซึ่งอาจเป็นข้อมูลที่เป็นความลับ
- ไม่บันทึก Log: ทำให้ยากต่อการวิเคราะห์และแก้ไขปัญหา
- จัดการ Error ไม่ถูกต้อง: ทำให้โปรแกรมทำงานผิดพลาดหรือหยุดทำงาน
สรุป: การจัดการ Error ที่ไม่ได้ถูก Handle เป็นสิ่งสำคัญในการพัฒนาโปรแกรม PHP ที่มีคุณภาพ การใช้ `set_error_handler()` ร่วมกับการแปลง Error เป็น Exception และการบันทึก Log จะช่วยให้เราสามารถจัดการข้อผิดพลาดได้อย่างมีประสิทธิภาพและทำให้โปรแกรมของเราทำงานได้อย่างราบรื่น