ดักจับข้อผิดพลาดใน PHP ด้วย try...catch
ในที่สุด PHP 5 ก็สามารถดักจับข้อผิดพลาด (Exception handling) เหมือนกับภาษาอื่นๆ ซักที Exception คือสถานการณ์ที่โปรแกรมทำงานพลาด แทนที่จะปล่อยให้โปรแกรมหยุดทำงาน เราสามารถเขียนโปรแกรมดักจับข้อผิดพลาดเพื่อควบคุมโปรแกรมต่ออีกหน่อยว่าโปรแกรมควรจะทำอะไรเวลาเจอข้อผิดพลาดนั้น
วิธีดักจับข้อผิดพลาดแบบเดิมๆ
สมมติให้ average เป็นฟังก์ชันในการคำนวณค่าเฉลี่ย โดยเอา $sum หาร $n ($sum เป็นผลรวมทั้งหมดและ $n เป็นจำนวนข้อมูล) เรารู้ว่าฟังก์ชันนี้จะทำงานผิดพลาดเมื่อ $n เป็น 0 จะไม่สามารถคำนวณค่า $sum/$n ได้ เพราะการหารด้วย 0 ไม่นิยาม เราจึงออกแบบโปรแกรมให้คืนค่า -1 เมื่อไม่สามารถคำนวณค่าได้
<?php function average($sum, $n) { if($total == 0) return -1; // ฟังก์ชันนี้จะคืนค่า -1 ถ้าไม่สามารถคำนวณค่าเฉลี่ย return $sum / $n; } $avg = average(100, 0); if($avg == -1) echo "ไม่สามารถหาค่าเฉลี่ยได้ เพราะจำนวนข้อมูลเป็น 0"; else { echo "Average = ", $avg; // do something else here } ?>
โปรแกรมจะคำนวณได้ตามปกติ และแสดงข้อผิดพลาดได้ตามปกติ… แต่เอ.. มันจะไม่ปกติก็ต่อเมื่อ ผลการคำนวณค่าเฉลี่ย ($sum / $n) มีค่าเป็น -1 ซึ่งซ้ำกับค่าที่เราใช้ในการบอกว่าฟังก์ชันคำนวณค่าเฉลี่ยไม่ได้ เราจะมีวิธีแก้ยังไง?….แอบเฉลยก่อน… ก็ลองใช้ try…catch ดูสิครับ
ดักจับข้อผิดพลาดด้วย try…catch
ดูโค้ดที่แล้ว ลองคิดดูว่า ถ้าโปรแกรมเราต้องเรียก average ซัก 3 ครั้ง เราจะต้องมี if กับ else เพิ่มขึ้นมาอีก 3 อัน แล้วถ้ามันซ้อนๆ กัน โปรแกรมเราจะมี if…else ที่ซ้อนๆ กันอีกเยอะแยะมากมาย เรามาลองดูวิธีดักจับเหมือนเดิม แต่เปลี่ยนมาใช้ try…catch แทน
<?php function average($sum, $n) { if($total == 0) throw new Exception("ไม่สามารถหาค่าเฉลี่ยได้ เพราะจำนวนข้อมูลเป็น 0"); //แก้ไขที่บรรทัดนี้ return $sum / $n; } try { $avg= average(100, 0); echo "Average = ", $avg; } catch (Exception $e) { echo $e->getMessage(), " at line ", $e->getLine(); } ?>
จากโค้ดข้างบนจะเห็นว่า โปรแกรมของเราสะอาดกว่าเดิมขึ้นเยอะ เพราะ ตัวดักจับ error ถูกแยกออกมาอยู่ในส่วน catch อย่างชัดเจน
try, throw, และ catch
try { // โค้ดที่อาจทำให้เกิด Exception // สามารถเขียนโค้ดปนอยู่กับโปรแกรมปกติได้ } catch (Exception $e) { // เมื่อมี Exception (ข้อผิดพลาด) เกิดขึ้นในบรรทัดใดบรรทัดหนึ่งด้านบน // โค้ดที่อยู่ในส่วน catch จะถูกเรียกทำงานแทน โดยตัวแปร $e (ตั้งชื่ออื่นก็ได้) // มีชนิดเป็น Exception Object จะเก็บค่าว่า Exception เนี่ยเกิดขึ้นที่บรรทัดไหน // มีข้อความบอก Error ว่าอย่างไรบ้าง }
ในส่วนของฟังก์ชันที่เราเรียกหรือโค้ดที่อยู่ใน try จะมีคำสั่ง throw ที่ใช้ในการโยนข้อผิดพลาด…. เอ๋!? โยนทำไมเหรอ?… ก็โยนข้อผิดพลาดมาให้ catch จัดการต่อไปว่าจะทำอะไรดีกับข้อผิดพลาดนั้น นั่นเองครับ ดังนั้นโค้ดบรรทัดต่อๆ ที่อยู่ใต้บรรทัดที่ throw จะไม่ถูกเรียกใช้งาน
คำสั่ง throw จะต้องตามด้วย Exception Object ที่ระบุว่าข้อผิดพลาดที่เกิดขึ้นนั้นคือข้อผิดพลาดอะไร? ลองดูว่า Exception Object ของ PHP มี method, properties อะไรให้เราใช้บ้าง
Exception class
<?php class Exception { protected $message = 'Unknown exception'; // ข้อความที่บอกว่าข้อผิดพลาดนี้คืออะไร protected $code = 0; // เราสามารถระบุหมายเลขข้อผิดพลาดเพื่อใช้ในโปรแกรมของเราเองได้ protected $file; // ไฟล์ที่เกิดข้อผิดพลาด (PHP ระบุให้ หรือจะแก้เองก็ได้) protected $line; // บรรทัดที่เกิดข้อผิดพลาด function __construct($message = null, $code = 0); // constructor ของ class นี้ final function getMessage(); // เรียกดู $message (ข้อความที่บอกว่าข้อผิดพลาดนี้คืออะไร) final function getCode(); // เรียกดู $code (หมายเลขของข้อผิดพลาด) final function getFile(); // เรียกดู $file (ไฟล์ที่ throw ข้อผิดพลาดนี้ออกมา) final function getLine(); // เรียกดู $line (บรรทัดที่ก่อให้เกิดข้อผิดพลาด) final function getTrace(); // array ที่เก็บว่ามีการเรียกฟังก์ชันซ้อนๆ กันผ่านฟังก์ชันอะไรบ้าง final function getTraceAsString(); // คล้ายกับ getTrace() แต่เป็นข้อมูลที่ถูกจัดรูปแบบให้เป็น string แล้ว /* Overrideable (สามารถแทนที่ด้วยฟังก์ชันของเราเองได้) */ function __toString(); // คำสั่งที่ใช้แสดงผลวัตถุนี้เป็นข้อความ } ?>
เราสามารถสร้างคลาสใหม่ที่ extend คลาส Exception ที่มีอยู่แล้วได้ เพื่อปรับแต่งให้เหมาะสมกับการใช้งาน ดูตัวอย่างการ extend ได้ที่ PHP: Exceptions - Manual
สรุป
การดักจับข้อผิดพลาด หรือ Exception ต่างๆ สามารถช่วยให้โปรแกรมของเราดูสะอาดขึ้น ไม่มี if ซ้อนกันเยอะๆ ลึกๆ ไม่ต้องใช้คำสั่ง die ทำให้เมื่อเกิดข้อผิดพลาด โปรแกรมก็ยังสามารถทำงานต่อไปได้ และยังสามารถแจ้งผู้ใช้ให้ทราบถึงข้อผิดพลาดนั้นได้อย่างเป็นมิตรกับผู้ใช้ (user-friendly)
ขอบคุณมากครับ กำลังหาอยู่ ไม่นึกว่าจะเจอจากเว็บไทย
ขอบคุณครับ
ขอบคุณครับ.............
แปล Text-Book อยู่ตั้งนาน
Post new comment