PHP حاول التقاط مثال: البرنامج التعليمي للاستثناءات والأخطاء
⚡ ملخص ذكي
تُساهم معالجة الأخطاء والاستثناءات في لغة PHP في الحفاظ على استقرار التطبيقات وأمانها من خلال إدارة الحالات غير المتوقعة بدلاً من عرض الأخطاء الخام. يشرح هذا الدليل الفرق بين الأخطاء والاستثناءات، وعبارات die، ومعالجات الأخطاء المخصصة، ومستويات الإبلاغ عن الأخطاء، ونموذج الاستثناءات try وthrow وcatch مع أنواع استثناءات متعددة.
ما هو الاستثناء؟
الخطأ هو نتيجة برنامج غير متوقعة لا يمكن للبرنامج نفسه معالجتها.
يتم حل الأخطاء عن طريق إصلاح البرنامج. مثال على الخطأ هو حلقة لا نهائية لا تتوقف عن التنفيذ أبدًا.
الاستثناء هو نتيجة غير متوقعة للبرنامج يمكن للبرنامج نفسه التعامل معها.
ومن أمثلة الاستثناءات محاولة فتح ملف غير موجود.
يمكن التعامل مع هذا الاستثناء إما عن طريق إنشاء الملف أو تقديم خيار البحث عن الملف للمستخدم.
لماذا يتم التعامل مع الاستثناءات؟
- تجنب النتائج غير المتوقعة على صفحاتنا، والتي قد تكون مزعجة للغاية أو مثيرة للضيق لمستخدمينا النهائيين
- تحسين أمان تطبيقاتنا من خلال عدم الكشف عن المعلومات التي قد يستخدمها المستخدمون الضارون لمهاجمة تطبيقاتنا
- تُستخدم استثناءات PHP لتغيير التدفق الطبيعي للبرنامج في حالة حدوث أي خطأ متوقع.
معالجة أخطاء PHP
عند حدوث خطأ، وفقًا لإعدادات التكوين لديك، PHP يعرض رسالة الخطأ في متصفح الويب مع المعلومات المتعلقة بالخطأ الذي حدث.
توفر لغة PHP عدة طرق للتعامل مع الأخطاء. سنستعرض ثلاث طرق شائعة الاستخدام:
- تصريحات يموت تجمع دالة die بين دالتي echo و exit في دالة واحدة. وهي مفيدة للغاية عندما نريد إخراج رسالة وإيقاف تنفيذ البرنامج النصي عند حدوث خطأ.
- معالجات الأخطاء المخصصة - هذه هي الوظائف التي يحددها المستخدم والتي يتم استدعاؤها عند حدوث خطأ.
- الإبلاغ عن الأخطاء في PHP – تعتمد رسالة الخطأ على إعدادات الإبلاغ عن أخطاء PHP لديك. هذه الطريقة مفيدة جدًا في بيئة التطوير عندما لا تعرف سبب الخطأ. يمكن أن تساعدك المعلومات المعروضة في تصحيح أخطاء تطبيقك.
أمثلة على التعامل مع الأخطاء
لنلقِ نظرة الآن على بعض الأمثلة البسيطة التي تتضمن إجراءات معالجة الأخطاء.
لنفترض أن لدينا عملية حسابية قد تؤدي إلى قسمة عدد على صفر. نريد معالجة هذه الحالة بشكل صحيح بدلاً من السماح لـ PHP بعرض خطأ مباشر.
يطبق الكود أدناه المثال أعلاه.
<?php
$denominator = 0;
echo 2 / $denominator;
?>
بافتراض أنك قمت بحفظ الملف simple_error.php في مجلد phptuts، افتح URL http://localhost/phptuts/simple_error.php
سوف تحصل على النتائج التالية
كما ترون من النتائج المذكورة أعلاه، فإن ذلك يجعل تطبيقنا يبدو غير احترافي ويمكن أن يكون مزعجًا للمستخدم.
سنقوم بتعديل الكود أعلاه وكتابة معالج للأخطاء للتطبيق.
<?php $denominator = 0; if ($denominator != 0) { echo 2 / $denominator; } else { echo "cannot divide by zero (0)"; } ?>
بافتراض أنك قمت بحفظ الكود أعلاه باسم error_handling.php، افتح URL http://localhost/phptuts/error_handling.php
ملاحظة: من الممارسات الأمنية الجيدة عرض رسالة مثل تلك الموضحة أعلاه بدلاً من عرض رسالة خام مثل "الملف غير موجود".
دعونا نلقي نظرة على مثال آخر يستخدم معالج أخطاء مخصص.
سيتم تعيين معالج الأخطاء المخصص كوظيفة معالجة أخطاء PHP الافتراضية وسيعرض بشكل أساسي رقم الخطأ والرسالة.
يوضح الكود أدناه تنفيذ المثال أعلاه.
<?php function my_error_handler($error_no, $error_msg) { echo "Oops, something went wrong:"; echo "Error number: [$error_no]"; echo "Error Description: [$error_msg]"; } set_error_handler("my_error_handler"); echo (5 / 0); ?>
فتح URL http://localhost/phptuts/custom_error_handler.phpستحصل على النتائج التالية.
كما ترون من المثال أعلاه، فإن معالجات الأخطاء المخصصة قوية بالمعنى التالي:
- أنها تسمح لنا بتخصيص رسائل الخطأ.
- يمكن أن يتضمن معالج الأخطاء المخصص أيضًا تسجيل الأخطاء في ملف أو قاعدة بيانات، وإرسال بريد إلكتروني إلى المطور، وإجراءات مماثلة.
لننتقل الآن إلى النوع الثالث من معالجة الأخطاء. سنستخدم دالة error_reporting المدمجة في PHP. ولها الصيغة الأساسية التالية.
<?php error_reporting($reporting_level); ?>
هنا،
- "error_reporting" هي وظيفة الإبلاغ عن الأخطاء في PHP
- يُعدّ "$reporting_level" خيارًا اختياريًا، ويمكن استخدامه لتحديد مستوى الإبلاغ. في حال عدم تحديد مستوى الإبلاغ، سيستخدم PHP مستوى الإبلاغ الافتراضي عن الأخطاء كما هو مُحدد في ملف php.ini.
| مستوى التقارير | الوصف | مثال |
|---|---|---|
| تحذير | يعرض رسائل التحذير فقط. لا يوقف تنفيذ البرنامج النصي | error_reporting(E_WARNING); |
| E_NOTICE | يعرض الإشعارات التي يمكن أن تحدث أثناء التنفيذ العادي لأحد البرامج أو قد تكون خطأ. | الإبلاغ عن الأخطاء (E_NOTICE)؛ |
| E_USER_ERROR | يعرض الأخطاء التي يُنشئها المستخدم، أي معالج أخطاء مخصص | error_reporting(E_USER_ERROR); |
| E_USER_WARNING | يعرض رسائل التحذير التي أنشأها المستخدم | error_reporting(E_USER_WARNING); |
| E_USER_NOTICE | يعرض الإشعارات التي أنشأها المستخدم | error_reporting(E_USER_NOTICE); |
| E_RECOVERABLE_ERROR | يعرض الأخطاء غير الخطيرة والتي يمكن معالجتها باستخدام معالجات الأخطاء المخصصة | error_reporting(E_RECOVERABLE_ERROR); |
| E_ALL | يعرض جميع الأخطاء والتحذيرات | الإبلاغ عن الخطأ(E_ALL); |
الفرق بين الأخطاء والاستثناء
- يتم طرح الاستثناءات ويهدف إلى التقاطها، بينما تكون الأخطاء غير قابلة للاسترداد بشكل عام.
- تُعالج الاستثناءات بطريقة كائنية التوجه. وهذا يعني أنه عند حدوث استثناء، يتم إنشاء كائن استثناء يحتوي على تفاصيل الاستثناء.
يوضح الجدول أدناه أساليب كائن الاستثناء.
| الأسلوب | الوصف | مثال |
|---|---|---|
| getMessage () | يعرض رسالة الاستثناء |
<?php
echo $e->getMessage();
?>
|
| دولار فقط واحصل على خصم XNUMX% على جميع Code() | يعرض الرمز الرقمي الذي يمثل الاستثناء |
<?php
echo $e->getCode();
?>
|
| خذ الملف() | يعرض اسم الملف والمسار الذي حدث فيه الاستثناء |
<?php
echo $e->getFile();
?>
|
| الحصول على خط() | يعرض رقم السطر الذي حدث فيه الاستثناء |
<?php
echo $e->getLine();
?>
|
| دولار فقط واحصل على خصم XNUMX% على جميع Tracه () | يعرض مجموعة من الخلفtrace قبل الاستثناء |
<?php print_r( $e->getTrace()); ?> |
| الحصول على السابق () | يعرض الاستثناء السابق قبل الاستثناء الحالي |
<?php
echo $e->getPrevious();
?>
|
| دولار فقط واحصل على خصم XNUMX% على جميع TraceAsString() | يعرض الجزء الخلفيtrace من الاستثناء كسلسلة نصية بدلاً من مصفوفة |
<?php
echo $e->getTraceAsString();
?>
|
| __إلى سلسلة() | يعرض الاستثناء بأكمله كسلسلة |
<?php
echo $e->__toString();
?>
|
فيما يلي بناء الجملة الأساسي لطرح استثناء.
<?php throw new Exception("This is an exception example"); ?>
هنا،
- "رمي" هي الكلمة الأساسية المستخدمة لطرح الاستثناء
- تقوم الدالة "new Exception(…)" بإنشاء كائن استثناء وتمرير السلسلة "This is an exception example" كمعامل رسالة.
يؤدي الكود أعلاه إلى إخراج الرسالة التالية.
سنستعرض الآن مثالاً يُطبّق استثناءات throw و catch. سنُعدّل المثال السابق ونُضيف إليه try و throw و catch.
يحتوي على بناء الجملة الأساسي التالي.
<?php try { // code goes here that could potentially throw an exception } catch (Exception $e) { // exception handling code goes here } ?>
هنا،
- "try{...}" هي مجموعة التعليمات البرمجية التي سيتم تنفيذها والتي من المحتمل أن تؤدي إلى حدوث استثناء
- "catch(Exception $e){...}" هو كتلة التعليمات البرمجية التي تلتقط الاستثناء الذي تم طرحه وتقوم بتعيين كائن الاستثناء للمتغير $e.
يُظهر الكود أدناه مثالًا أساسيًا للاستثناء مع تطبيق try و throw و catch. يقوم البرنامج عمدًا برمي استثناء ثم يقوم بالتقاطه.
<?php try { $var_msg = "This is an exception example"; throw new Exception($var_msg); } catch (Exception $e) { echo "Message: " . $e->getMessage(); echo ""; echo "getCode(): " . $e->getCode(); echo ""; echo "__toString(): " . $e->__toString(); } ?>
فتح URL http://localhost/phptuts/exception_handling.phpستحصل على النتائج التالية.
من الممكن أيضًا إنشاء استثناءات متعددة لعبارة try واحدة في PHP اعتمادًا على نوع الاستثناء الذي تم طرحه.
انظر المقال على MySQL، الوصول إلى البيانات في لغة PHP للحصول على أمثلة لتنفيذ استثناءات متعددة.
استثناءات متعددة
تستخدم الاستثناءات المتعددة عدة كتل catch لمعالجة الاستثناءات التي تم طرحها. وتكون الاستثناءات المتعددة مفيدة عندما:
- تريد عرض رسالة مخصصة بناءً على الاستثناء الذي تم طرحه
- تريد إجراء عملية فريدة بناءً على الاستثناء الذي تم طرحه
يوضح المخطط الانسيابي أدناه كيفية عمل الاستثناءات المتعددة.
لنلقِ نظرة على مثال يستخدم استثناءات متعددة. سنقوم بتعديل الكود الذي يقسم عددًا على المقام المُمرر.
نتوقع حدوث نوعين من الاستثناءات:
- القسمة على صفر
- القسمة على رقم سلبي
لتبسيط الأمر، سنعرض نوع الاستثناء فقط في كتل catch. تُستخدم فئة Exception المدمجة في PHP لإطلاق الاستثناءات. سننشئ فئتين ترثان من فئة Exception ونستخدمهما لإطلاق الاستثناءات.
يوضح الكود أدناه التنفيذ.
<?php class DivideByZeroException extends Exception {}; class DivideByNegativeException extends Exception {}; function process($denominator) { try { if ($denominator == 0) { throw new DivideByZeroException(); } else if ($denominator < 0) { throw new DivideByNegativeException(); } else { echo 25 / $denominator; } } catch (DivideByZeroException $ex) { echo "DIVIDE BY ZERO EXCEPTION!"; } catch (DivideByNegativeException $ex) { echo "DIVIDE BY NEGATIVE NUMBER EXCEPTION!"; } catch (Exception $x) { echo "UNKNOWN EXCEPTION!"; } } process(0); ?>
اختبار الكود
سنفترض أنك قمت بحفظ ملف multiple_exceptions.php في مجلد phptuts.
استعرض للوصول إلى URL http://localhost/phptuts/multiple_exceptions.php
قم بالرجوع إلى ملف PHP ومرر -1 كمعلمة كما هو موضح في الرسم التخطيطي التالي.
استعرض للوصول إلى URL http://localhost/phptuts/multiple_exceptions.phpما النتائج التي تحصل عليها؟ الآن مرر الرقم 3 كمعامل. ما النتائج التي تحصل عليها؟
كتلة finally ونموذج خطأ PHP 7
يُضيف PHP الحديث عنصرين مهمين إلى النموذج المذكور أعلاه. يتم تنفيذ كتلة finally بعد كتلة try و catch بغض النظر عما إذا تم طرح استثناء أم لا، مما يجعلها مثالية لعمليات التنظيف مثل إغلاق ملف أو اتصال قاعدة بيانات.
منذ PHP 7، يتم طرح العديد من الأخطاء الفادحة السابقة ككائنات خطأ. يُطبّق كل من Exception وError واجهة Throwable، لذا يمكن لكتلة catch (\Throwable $e) التعامل مع أي منهما.
<?php try { $result = 10 / 0; } catch (DivisionByZeroError $e) { echo "Caught: " . $e->getMessage(); } finally { echo "This message always runs"; } ?>
هنا، القسمة على صفر تُسبب خطأ DivisionByZeroError في PHP 8، ويقوم كتلة catch بالإبلاغ عنه، ويتم تشغيل كتلة finally دائمًا، وطباعة رسالتها سواء حدث خطأ أم لا.









