سؤال

أنا على دراية ببعض الأساسيات، ولكن ما أود معرفة المزيد عنه هو متى ولماذا يجب استخدام معالجة الأخطاء (بما في ذلك طرح الاستثناءات) في PHP، خاصة على موقع مباشر أو تطبيق ويب.هل هو شيء يمكن الإفراط في استخدامه، وإذا كان الأمر كذلك، كيف يبدو الإفراط في الاستخدام؟وهل هناك حالات لا ينبغي استخدامها؟وأيضًا، ما هي بعض المخاوف الأمنية الشائعة فيما يتعلق بمعالجة الأخطاء؟

هل كانت مفيدة؟

المحلول

شيء واحد يجب إضافته إلى ما قيل بالفعل هو أنه من الأهمية بمكان أن تقوم بتسجيل أي أخطاء في تطبيق الويب الخاص بك في السجل.بهذه الطريقة، كما يقترح Jeff "Coding Horror" Atwood، ستعرف متى يواجه المستخدمون مشكلة في تطبيقك (بدلاً من "سؤالهم عن المشكلة").

للقيام بذلك، أوصي بالنوع التالي من البنية التحتية:

  • قم بإنشاء جدول "تعطل" في قاعدة البيانات الخاصة بك ومجموعة من فئات المجمّع للإبلاغ عن الأخطاء.أوصي بتعيين فئات الأعطال ("الحظر"، "الأمان"، "خطأ/تحذير PHP" (مقابل الاستثناء)، وما إلى ذلك).
  • في كل التعليمات البرمجية الخاصة بمعالجة الأخطاء، تأكد من تسجيل الخطأ.يعتمد القيام بذلك باستمرار على مدى جودة إنشاء واجهة برمجة التطبيقات (الخطوة أعلاه) - يجب أن يكون كذلك تافه لتسجيل الأعطال إذا تم القيام بها بشكل صحيح.

رصيد إضافي:في بعض الأحيان، ستكون أعطالك عبارة عن أعطال على مستوى قاعدة البيانات:أي.خادم قاعدة البيانات معطل، وما إلى ذلك.إذا كان الأمر كذلك، فستفشل البنية الأساسية لتسجيل الأخطاء (أعلاه) (لا يمكنك تسجيل التعطل في قاعدة البيانات لأن السجل يحاول الكتابة إلى قاعدة البيانات).في هذه الحالة، أود أن أكتب منطق تجاوز الفشل في فئة مجمع الأعطال الخاصة بك إلى أي منهما

  • إرسال بريد إلكتروني إلى المشرف، و/أو
  • تسجيل تفاصيل الحادث في ملف نصي عادي

كل هذا يبدو وكأنه مبالغة، ولكن صدقني، هذا يحدث فرقًا في ما إذا كان طلبك مقبولًا باعتباره "مستقرًا" أو "غير مستقر".يأتي هذا الاختلاف من حقيقة أن جميع التطبيقات تبدأ بشكل غير مستقر/تتعطل طوال الوقت، ولكن هؤلاء المطورين الذين يعرفون جميع المشكلات المتعلقة بتطبيقاتهم لديهم فرصة لإصلاحها فعليًا.

نصائح أخرى

بشكل تقريبي، الأخطاء هي إرث في PHP، في حين أن الاستثناءات هي الطريقة الحديثة لمعالجة الأخطاء.إن أبسط شيء إذن هو إعداد معالج الأخطاء الذي يطرح استثناءً.وبهذه الطريقة يتم تحويل جميع الأخطاء إلى استثناءات، ومن ثم يمكنك ببساطة التعامل مع نظام واحد لمعالجة الأخطاء.سيقوم التعليمة البرمجية التالية بتحويل الأخطاء إلى استثناءات لك:

function exceptions_error_handler($severity, $message, $filename, $lineno) {
  if (error_reporting() == 0) {
    return;
  }
  if (error_reporting() & $severity) {
    throw new ErrorException($message, 0, $severity, $filename, $lineno);
  }
}
set_error_handler('exceptions_error_handler');
error_reporting(E_ALL ^ E_STRICT);

ومع ذلك، هناك حالات قليلة، حيث تم تصميم التعليمات البرمجية خصيصًا للتعامل مع الأخطاء.على سبيل المثال، schemaValidate طريقة DomDocument يثير تحذيرات، عند التحقق من صحة وثيقة.إذا قمت بتحويل الأخطاء إلى استثناءات، فسوف يتوقف التحقق من الصحة بعد الفشل الأول.في بعض الأحيان يكون هذا هو ما تريده، ولكن عند التحقق من صحة مستند، قد ترغب فيه بالفعل الجميع الفشل.في هذه الحالة، يمكنك تثبيت معالج الأخطاء بشكل مؤقت، والذي يقوم بجمع الأخطاء.إليك مقتطفًا صغيرًا استخدمته لهذا الغرض:

class errorhandler_LoggingCaller {
  protected $errors = array();
  function call($callback, $arguments = array()) {
    set_error_handler(array($this, "onError"));
    $orig_error_reporting = error_reporting(E_ALL);
    try {
      $result = call_user_func_array($callback, $arguments);
    } catch (Exception $ex) {
      restore_error_handler();
      error_reporting($orig_error_reporting);
      throw $ex;
    }
    restore_error_handler();
    error_reporting($orig_error_reporting);
    return $result;
  }
  function onError($severity, $message, $file = null, $line = null) {
    $this->errors[] = $message;
  }
  function getErrors() {
    return $this->errors;
  }
  function hasErrors() {
    return count($this->errors) > 0;
  }
}

وحالة الاستخدام:

$doc = new DomDocument();
$doc->load($xml_filename);
$validation = new errorhandler_LoggingCaller();
$validation->call(
  array($doc, 'schemaValidate'),
  array($xsd_filename));
if ($validation->hasErrors()) {
  var_dump($validation->getErrors());
}

تؤدي الأخطاء غير المعالجة إلى إيقاف البرنامج النصي، وهذا وحده سبب وجيه للتعامل معها.

بشكل عام، يمكنك استخدام كتلة Try-Catch للتعامل مع الأخطاء

try
{
    // Code that may error
}
catch (Exception $e)
{
    // Do other stuff if there's an error
}

إذا كنت تريد إيقاف ظهور الخطأ أو رسالة التحذير على الصفحة، فيمكنك بادئة المكالمة بعلامة @ مثل ذلك.

 @mysql_query($query);

ومع ذلك، بالنسبة للاستعلامات، من الجيد عمومًا القيام بشيء كهذا حتى يكون لديك فكرة أفضل عما يحدث.

@mysql_query($query)
    or die('Invalid query: ' . mysql_error() . '<br />Line: ' . __LINE__ . '<br />File: ' . __FILE__ . '<br /><br />');

يجب عليك استخدام معالجة الأخطاء في الحالات التي لا يكون لديك فيها تحكم واضح في البيانات التي يعمل عليها البرنامج النصي.أميل إلى استخدامه بشكل متكرر على سبيل المثال في أماكن مثل التحقق من صحة النموذج.إن معرفة كيفية اكتشاف الأماكن المعرضة للأخطاء في التعليمات البرمجية يتطلب بعض الممارسة:بعض الحالات الشائعة تكون بعد استدعاءات الوظائف التي تُرجع قيمة، أو عند التعامل مع نتائج من استعلام قاعدة البيانات.يجب ألا تفترض أبدًا أن العائد من الوظيفة سيكون ما تتوقعه، ويجب عليك التأكد من البرمجة تحسبًا.ليس عليك استخدام كتل المحاولة/الالتقاط، على الرغم من أنها مفيدة.في كثير من الأحيان يمكنك القيام بذلك من خلال التحقق البسيط من حالة/آخر.

تسير معالجة الأخطاء جنبًا إلى جنب مع ممارسات البرمجة الآمنة، حيث يوجد الكثير من "الأخطاء" التي لا تتسبب في تعطل البرنامج النصي الخاص بك.على الرغم من أنها لا تتعلق بشكل صارم بمعالجة الأخطاء في حد ذاتها، إلا أن Addbytes تحتوي على سلسلة مقالات جيدة مكونة من 4 مقالات حول بعض أساسيات برمجة PHP الآمنة والتي يمكنك العثور عليها هنا.هناك الكثير من الأسئلة الأخرى هنا حول Stackoverflow حول موضوعات مثل mysql_real_escape_string و التعبيرات العادية والتي يمكن أن تكون قوية جدًا في تأكيد محتوى البيانات التي أدخلها المستخدم.

أفضل ممارسة IMHO هي استخدام النهج التالي:1.إنشاء خطأ/معالج خطأ/استثناء 2.ابدأه على التطبيق بدءًا من 3.تعامل مع جميع أخطائك من الداخل هناك

<?php

تصحيح فئة {

    public static setAsErrorHandler() {
         set_error_handler(array(__CLASS__, '__error_handler'));
    }

public static function __error_handler($errcode, $errmsg, $errfile, $errline) {
       if (IN DEV) {
                print on screen
           }
           else if (IN PRO) {
                log and mail
           } 
    }

}

تصحيح::setAsErrorHandler();

?>

بدلاً من إخراج خطأ mysql_error، يمكنك تخزينه في سجل.وبهذه الطريقة يمكنك تتبع الخطأ (ولا تعتمد على المستخدمين للإبلاغ عنه) ويمكنك الدخول وإزالة المشكلة.

أفضل معالجة للأخطاء هي النوع الذي يكون شفافًا للمستخدم، دع الكود الخاص بك يحل المشكلة، دون الحاجة إلى إشراك ذلك المستخدم.

إلى جانب معالجة الأخطاء على الفور في التعليمات البرمجية الخاصة بك، يمكنك أيضًا الاستفادة منها

http://us.php.net/manual/en/function.set-exception-handler.php
و
http://us.php.net/manual/en/function.set-error-handler.php

أجد أن إعداد معالج الاستثناء الخاص بك مفيد بشكل خاص.عند حدوث استثناء، يمكنك إجراء عمليات مختلفة اعتمادًا على نوع الاستثناء.

السابق:عندما mysql_connet عودة المكالمة FALSE أرمي أ new DBConnectionException(mysql_error()) والتعامل معها بطريقة "خاصة":سجل الخطأ، ومعلومات اتصال قاعدة البيانات (المضيف، واسم المستخدم، وكلمة المرور) وما إلى ذلك، وربما أرسل بريدًا إلكترونيًا إلى فريق التطوير لإعلامهم بأن هناك شيئًا ما قد يكون خطأً حقيقيًا في قاعدة البيانات

أستخدم هذا لتكمل معالجة الأخطاء القياسية.لا أوصي بالإفراط في استخدام هذا النهج

يعد منع الأخطاء باستخدام @ بطيئًا جدًا.

يمكنك أيضًا استخدام نماذج Google للتعرف على الاستثناءات وتحليلها، دون الحاجة إلى الاحتفاظ بقاعدة بيانات أو خادم يمكن الوصول إليه بشكل عام.هناك البرنامج التعليمي هنا وهذا ما يفسر العملية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top