وتستخدم استثناءات لتغيير التدفق الطبيعي للالسيناريو في حالة حدوث الخطأ المحدد.
ما هو استثناء
مع PHP 5 جاء بطريقة جديدة وجوه المنحى في التعامل مع الأخطاء.
يستخدم معالجة الاستثناء لتغيير التدفق الطبيعي للبتنفيذ التعليمات البرمجية إذا كان الخطأ المحدد (exceptional) تحدث حالة. وتسمى هذه الحالة استثناء.
هذا هو ما يحدث عادة عندما يتم تشغيل استثناء:
- يتم حفظ الدولة كود الحالية
- سوف بتنفيذ التعليمات البرمجية التحول إلى مسبقا (custom) وظيفة معالج استثناء
- تبعا للحالة، معالج قد ثم استئناف التنفيذ من الدولة كود المحفوظة، إنهاء تنفيذ البرنامج النصي أو يستمر البرنامج النصي من موقع مختلف في رمز
وسوف نعرض مختلف أساليب معالجة الأخطاء:
- الاستخدام الأساسي من الاستثناءات
- إنشاء معالج استثناء مخصصة
- استثناءات متعددة
- إعادة رمي استثناء
- وضع معالج استثناء المستوى الأعلى
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"
- قبض - A "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" كتلة يمسك استثناء ويعرض رسالة خطأ
استثناءات متعددة
فمن الممكن للبرنامج نصي لاستخدام استثناءات متعددة للتحقق من شروط متعددة.
ومن الممكن استخدام عدة كتل 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" كتلة يمسك استثناء ويعرض رسالة لتصحيح الخطأ
إذا كان استثناء القيت من customException الدرجة ولم تكن هناك الصيد customException، إلا أن الصيد استثناء قاعدة، والاستثناء أن تعالج هناك.
إعادة رمي الاستثناءات
في بعض الأحيان، عندما يتم طرح استثناء، قد ترغب في التعامل معها بشكل مختلف عن الطريقة القياسية. فمن الممكن لرمي استثناء للمرة الثانية ضمن "catch" كتلة.
وهناك سيناريو يجب إخفاء أخطاء النظام من المستخدمين. قد تكون أخطاء النظام المهم للالمبرمج، ولكنها لا تهم المستخدم. لجعل الأمور أسهل بالنسبة للمستخدم يمكنك إعادة رمي استثناء مع رسالة الاستعمال:
<?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" كتلة يمسك استثناء وإعادة يلقي واحد "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) في كتلة الصيد داخل كتلة المحاولة
وهناك قاعدة بسيطة: إذا كنت رمي شيء، لديك للقبض عليه.