ยกเว้นจะใช้ในการเปลี่ยนการไหลปกติของสคริปต์ถ้าข้อผิดพลาดเกิดขึ้นที่ระบุ
ข้อยกเว้นคืออะไร
ด้วย PHP 5 มาเป็นวิธีเชิงวัตถุใหม่ของการจัดการกับข้อผิดพลาด
การจัดการข้อยกเว้นใช้ในการเปลี่ยนการไหลปกติของการดำเนินรหัสถ้าข้อผิดพลาดที่ระบุ (exceptional) สภาพเกิดขึ้น สภาพนี้เรียกว่าเป็นข้อยกเว้น
นี่คือสิ่งที่เกิดขึ้นตามปกติเมื่อมีข้อยกเว้นจะถูกเรียก:
- รัฐรหัสปัจจุบันจะถูกบันทึกไว้
- โค้ดจะเปลี่ยนไปใช้ที่กำหนดไว้ล่วงหน้า (custom) ฟังก์ชั่นการจัดการข้อยกเว้น
- ทั้งนี้ขึ้นอยู่กับสถานการณ์ที่จัดการแล้วอาจกลับมาดำเนินการจากรัฐรหัสที่บันทึกไว้ยุติการดำเนินการสคริปต์หรือยังคงสคริปต์จากสถานที่ที่แตกต่างกันในรหัส
เราจะแสดงวิธีการจัดการข้อผิดพลาดที่แตกต่างกัน
- การใช้งานพื้นฐานของข้อยกเว้น
- การสร้างจัดการข้อยกเว้นที่กำหนดเอง
- ข้อยกเว้นหลาย
- Re-ขว้างปายกเว้น
- การตั้งค่าระดับบนสุดจัดการข้อยกเว้น
Note: ข้อยกเว้นควรจะใช้เฉพาะกับเงื่อนไขข้อผิดพลาดและไม่ควรนำมาใช้เพื่อข้ามไปยังสถานที่อื่นในรหัสที่จุดที่กำหนด
พื้นฐานของการใช้ข้อยกเว้น
เมื่อยกเว้นจะโยนรหัสต่อไปนี้ก็จะไม่ได้รับการดำเนินการและ PHP จะพยายามที่จะหาที่ตรงกัน "catch" บล็อก
หากมีข้อยกเว้นไม่ได้ถูกจับเป็นข้อผิดพลาดร้ายแรงจะออกกับ "Uncaught Exception" ข้อความ
ให้พยายามที่จะโยนข้อยกเว้นโดยไม่ต้องจับมัน
<?php
//create function with an exception
function checkNum($number) {
if($number>1) {
throw new Exception("Value must be 1 or below");
}
return true;
}
//trigger exception
checkNum(2);
?>
โค้ดข้างต้นจะได้รับข้อผิดพลาดเช่นนี้:
Fatal error : Uncaught exception 'Exception'
with message 'Value must be 1 or below' in C:\webfolder\test.php:6
Stack trace: #0 C:\webfolder\test.php(12):
checkNum(28) #1 {main} thrown in C:\webfolder\test.php on line 6
ลองโยนและจับ
เพื่อหลีกเลี่ยงข้อผิดพลาดจากตัวอย่างข้างต้นเราต้องสร้างโค้ดที่เหมาะสมในการจัดการข้อยกเว้น
รหัสข้อยกเว้นที่เหมาะสมควรจะรวมถึง:
- ลอง - ฟังก์ชั่นการใช้ข้อยกเว้นควรจะอยู่ใน "try" บล็อก หากยกเว้นไม่เรียกรหัสจะยังคงเป็นปกติ แต่ถ้าข้อยกเว้นเรียกยกเว้นจะ "thrown"
- โยน - นี่คือวิธีการที่คุณเรียกข้อยกเว้น แต่ละ "throw" จะต้องมีอย่างน้อยหนึ่ง "catch"
- จับ - เป็น "catch" กระชากดึงข้อยกเว้นและสร้างวัตถุที่มีข้อมูลข้อยกเว้น
ให้พยายามที่จะก่อให้เกิดข้อยกเว้นด้วยรหัสที่ถูกต้อง:
<?php
//create function with an exception
function checkNum($number) {
if($number>1) {
throw new Exception("Value must be 1 or below");
}
return true;
}
//trigger exception in a "try" block
try {
checkNum(2);
//If the exception is thrown, this text will not be shown
echo 'If you see this, the number is 1 or below';
}
//catch exception
catch(Exception $e) {
echo 'Message: ' .$e->getMessage();
}
?>
โค้ดข้างต้นจะได้รับข้อผิดพลาดเช่นนี้:
Message: Value must be 1 or below
ตัวอย่างอธิบาย:
โค้ดข้างต้นพ่นยกเว้นและจับมัน:
- checkNum() ฟังก์ชั่นจะถูกสร้างขึ้น มันจะตรวจสอบว่าเป็นจำนวนที่มีค่ามากกว่า 1 ถ้ามันเป็นยกเว้นจะโยน
- checkNum() ฟังก์ชั่นที่เรียกว่าใน "try" บล็อก
- ยกเว้นในกรณีที่ภายใน checkNum() ฟังก์ชั่นจะถูกโยนทิ้ง
- "catch" กระชากดึงข้อยกเว้นและสร้างวัตถุ ($e) ที่มีข้อมูลข้อยกเว้น
- เกิดข้อผิดพลาดจากการยกเว้นสะท้อนโดยการเรียก $e-> getMessage() จากวัตถุข้อยกเว้น
แต่วิธีหนึ่งที่จะได้รับรอบ "every throw must have a catch" กฎคือการตั้งค่าการจัดการข้อยกเว้นระดับบนสุดที่จะจัดการกับข้อผิดพลาดที่ลื่นผ่าน
การสร้างชั้นยกเว้นที่กำหนดเอง
เพื่อสร้างจัดการข้อยกเว้นที่กำหนดเองคุณต้องสร้างชั้นเรียนพิเศษด้วยฟังก์ชั่นที่สามารถเรียกว่าเมื่อมีข้อยกเว้นเกิดขึ้นใน PHP ชั้นจะต้องเป็นส่วนหนึ่งของชั้นข้อยกเว้น
ชั้นยกเว้นที่กำหนดเองสืบทอดคุณสมบัติจากชั้นยกเว้นของ PHP และคุณสามารถเพิ่มฟังก์ชั่นที่กำหนดเองเพื่อมัน
ช่วยให้สร้างชั้นยกเว้น:
<?php
class customException extends Exception {
public function errorMessage() {
//error message
$errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile()
.': <b>'.$this->getMessage().'</b> is not a valid E-Mail address';
return $errorMsg;
}
}
$email = "[email protected]";
try {
//check if
if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
//throw exception if email is not valid
throw new customException($email);
}
}
catch (customException $e) {
//display custom message
echo $e->errorMessage();
}
?>
คลาสใหม่เป็นสำเนาของชนชั้นยกเว้นเก่าด้วยนอกเหนือจากที่ errorMessage() ฟังก์ชั่น เพราะมันเป็นสำเนาของชนชั้นเก่าและมันสืบทอดคุณสมบัติและวิธีการจากชั้นเก่าเราสามารถใช้วิธีการเรียนการยกเว้นเช่น getLine() และ getFile() และ getMessage()
ตัวอย่างอธิบาย:
โค้ดข้างต้นพ่นยกเว้นและจับมันมีระดับยกเว้นที่กำหนดเอง:
- customException() ชั้นที่ถูกสร้างขึ้นเป็นส่วนขยายของชั้นยกเว้นเก่า วิธีนี้จะสืบทอดวิธีการทั้งหมดและคุณสมบัติจากชั้นยกเว้นเก่า
- errorMessage() ฟังก์ชั่นจะถูกสร้างขึ้น ฟังก์ชั่นนี้จะส่งกลับข้อผิดพลาดถ้าอีเมลไม่ถูกต้อง
- ตัวแปร $ อีเมลถูกตั้งค่าเป็นสตริงที่ไม่ได้เป็นที่อยู่อีเมลที่ถูกต้อง
- "try" บล็อกจะถูกดำเนินการและยกเว้นจะโยนตั้งแต่อีเมลไม่ถูกต้อง
- "catch" บล็อก catches ข้อยกเว้นและแสดงข้อความข้อผิดพลาด
หลายข้อยกเว้น
มันเป็นไปได้สำหรับสคริปต์ที่จะใช้ข้อยกเว้นหลายเพื่อตรวจสอบหลายเงื่อนไข
มันเป็นไปได้ที่จะใช้บล็อกหลาย if..else, สวิทช์หรือรังข้อยกเว้นหลาย ข้อยกเว้นเหล่านี้สามารถใช้คลาสยกเว้นที่แตกต่างกันและกลับข้อความผิดพลาดที่แตกต่างกัน
<?php
class customException extends Exception
{
public function errorMessage()
{
//error message
$errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile()
.': <b>'.$this->getMessage().'</b> is not a valid E-Mail address';
return $errorMsg;
}
}
$email = "[email protected]";
try {
//check if
if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
//throw exception if email is not valid
throw new customException($email);
}
//check for "example" in mail address
if(strpos($email, "example") !== FALSE) {
throw new Exception("$email is an example e-mail");
}
}
catch (customException $e) {
echo $e->errorMessage();
}
catch(Exception $e) {
echo $e->getMessage();
}
?>
ตัวอย่างอธิบาย:
โค้ดข้างต้นการทดสอบสองเงื่อนไขและพ่นยกเว้นถ้าเงื่อนไขใด ๆ จะไม่ได้พบกับ:
- customException() ชั้นที่ถูกสร้างขึ้นเป็นส่วนขยายของชั้นยกเว้นเก่า วิธีนี้จะสืบทอดวิธีการทั้งหมดและคุณสมบัติจากชั้นยกเว้นเก่า
- errorMessage() ฟังก์ชั่นจะถูกสร้างขึ้น ฟังก์ชั่นนี้จะส่งกลับข้อผิดพลาดถ้าอีเมลไม่ถูกต้อง
- ตัวแปร $ อีเมลถูกตั้งค่าเป็นสตริงที่เป็นที่อยู่อีเมลที่ถูกต้อง แต่มีสตริง "example"
- "try" บล็อกจะถูกดำเนินการและข้อยกเว้นไม่ได้ส่งออกไปบนเงื่อนไขแรก
- เงื่อนไขที่สองเรียกยกเว้นตั้งแต่อีเมลมีสตริง "example"
- "catch" บล็อก catches ข้อยกเว้นและแสดงข้อความข้อผิดพลาดที่ถูกต้อง
หากข้อยกเว้นโยนเป็นของ customException ชั้นเรียนและไม่มีการจับ customException เพียงจับฐานข้อยกเว้นข้อยกเว้นจะได้รับการจัดการที่มี
Re-โยนข้อยกเว้น
บางครั้งเมื่อยกเว้นจะโยนคุณอาจต้องการที่จะจัดการกับมันแตกต่างจากวิธีการมาตรฐาน มันเป็นไปได้ที่จะโยนยกเว้นเป็นครั้งที่สองภายใน "catch" บล็อก
สคริปต์ควรซ่อนผิดพลาดของระบบจากผู้ใช้ ข้อผิดพลาดของระบบอาจมีความสำคัญสำหรับ coder แต่เป็นที่สนใจของผู้ใช้ไม่มี ที่จะทำให้สิ่งที่ง่ายสำหรับผู้ใช้ที่คุณสามารถ re-โยนข้อยกเว้นด้วยข้อความที่เป็นมิตรกับผู้ใช้:
<?php
class customException extends Exception {
public function errorMessage() {
//error message
$errorMsg = $this->getMessage().' is not a valid E-Mail address.';
return $errorMsg;
}
}
$email = "[email protected]";
try {
try {
//check for "example" in mail address
if(strpos($email, "example") !== FALSE) {
//throw exception if email is not valid
throw new Exception($email);
}
}
catch(Exception $e) {
//re-throw exception
throw new customException($email);
}
}
catch (customException $e) {
//display custom message
echo $e->errorMessage();
}
?>
ตัวอย่างอธิบาย:
โค้ดข้างต้นการทดสอบถ้าอีเมลที่อยู่มีสตริง "example" อยู่ในนั้นถ้ามันไม่ยกเว้นเป็นอีกครั้งที่โยน:
- customException() ชั้นที่ถูกสร้างขึ้นเป็นส่วนขยายของชั้นยกเว้นเก่า วิธีนี้จะสืบทอดวิธีการทั้งหมดและคุณสมบัติจากชั้นยกเว้นเก่า
- errorMessage() ฟังก์ชั่นจะถูกสร้างขึ้น ฟังก์ชั่นนี้จะส่งกลับข้อผิดพลาดถ้าอีเมลไม่ถูกต้อง
- ตัวแปร $ อีเมลถูกตั้งค่าเป็นสตริงที่เป็นที่อยู่อีเมลที่ถูกต้อง แต่มีสตริง "example"
- "try" บล็อกมีอีก "try" บล็อกที่จะทำให้มันเป็นไปได้ที่จะกลับมาโยนข้อยกเว้น
- ยกเว้นในกรณีที่มีการเรียกตั้งแต่อีเมลมีสตริง "example"
- "catch" บล็อก catches ข้อยกเว้นและอีกโยน "customException"
- "customException" ถูกจับและแสดงข้อความผิดพลาด
หากยกเว้นไม่ได้ถูกจับในปัจจุบัน "try" บล็อกก็จะหาจับบล็อกใน "higher levels"
ตั้งค่าการจัดการข้อยกเว้นระดับสูงสุด
set_exception_handler() ฟังก์ชั่นตั้งค่าฟังก์ชั่นที่ผู้ใช้กำหนดที่จะจัดการกับข้อยกเว้น uncaught ทั้งหมด
<?php
function myException($exception)
{
echo "<b>Exception:</b> " . $exception->getMessage();
}
set_exception_handler('myException');
throw new Exception('Uncaught Exception occurred');
?>
การส่งออกของรหัสดังกล่าวควรจะเป็นอะไรเช่นนี้
Exception: Uncaught Exception occurred
ในโค้ดข้างต้นไม่มี "catch" บล็อก แต่ระดับด้านบนจัดการข้อยกเว้นเรียก ฟังก์ชั่นนี้ควรจะใช้ในการจับข้อยกเว้น uncaught
กฎข้อยกเว้น
- รหัสอาจจะถูกล้อมรอบในบล็อกลองเพื่อช่วยจับข้อยกเว้นที่อาจเกิดขึ้น
- แต่ละคนพยายามบล็อกหรือ "throw" ต้องมีอย่างน้อยหนึ่งจับบล็อกที่สอดคล้องกัน
- จับหลายบล็อกสามารถนำมาใช้ในการจับการเรียนแตกต่างกันของข้อยกเว้น
- ยกเว้นจะถูกโยน (or re-thrown) ในการป้องกันการจับภายในบล็อกลอง
กฎง่าย: ถ้าคุณโยนสิ่งที่คุณจะต้องจับมัน