أساسيات PHP

أنواع الأخطاء ومعالجتها

13 دقيقة الدرس 26 من 45

أنواع الأخطاء ومعالجتها

فهم الأخطاء ومعالجتها بشكل صحيح أمر بالغ الأهمية لبناء تطبيقات PHP قوية. توفر PHP عدة أنواع من الأخطاء وآليات لمساعدتك في تحديد المشكلات وحلها في الكود الخاص بك.

أنواع أخطاء PHP

تحتوي PHP على عدة مستويات من الأخطاء تشير إلى خطورة المشكلات المختلفة:

<?php // 1. أخطاء التحليل (E_PARSE) - أخطاء بناء جملة قاتلة // echo "Hello World // علامة اقتباس إغلاق مفقودة - السكريبت لن يعمل // 2. الأخطاء القاتلة (E_ERROR) - أخطاء حرجة توقف التنفيذ // callNonExistentFunction(); // خطأ قاتل // 3. أخطاء التحذير (E_WARNING) - أخطاء غير قاتلة، يستمر السكريبت $file = fopen("nonexistent.txt", "r"); // تحذير: الملف غير موجود // 4. أخطاء الملاحظة (E_NOTICE) - مشكلات بسيطة، يستمر السكريبت echo $undefinedVariable; // ملاحظة: متغير غير معرف // 5. أخطاء الاستخدام القديم (E_DEPRECATED) - ميزات سيتم إزالتها // استخدام ميزات PHP القديمة يولد هذه التحذيرات // 6. الأخطاء الصارمة (E_STRICT) - اقتراحات لتحسين الكود // اقتراحات لممارسات برمجية أفضل ?>
ملاحظة: الأخطاء القاتلة وأخطاء التحليل ستوقف تنفيذ السكريبت فوراً، بينما التحذيرات والملاحظات تسمح للسكريبت بالاستمرار.

إعداد الإبلاغ عن الأخطاء

يمكنك التحكم في الأخطاء التي يتم الإبلاغ عنها وكيفية عرضها:

<?php // عرض جميع الأخطاء (للتطوير) error_reporting(E_ALL); ini_set('display_errors', 1); // عرض جميع الأخطاء ما عدا الملاحظات error_reporting(E_ALL & ~E_NOTICE); // إيقاف عرض الأخطاء (للإنتاج) error_reporting(0); ini_set('display_errors', 0); // تسجيل الأخطاء في ملف بدلاً من عرضها ini_set('log_errors', 1); ini_set('error_log', '/path/to/error.log'); // الإعداد الشائع للإنتاج error_reporting(E_ALL); ini_set('display_errors', 0); ini_set('log_errors', 1); ?>
تحذير: لا تعرض الأخطاء أبداً في بيئة الإنتاج! قم دائماً بتسجيلها في ملف واعرض رسائل ودية للمستخدم بدلاً من ذلك.

معالجات الأخطاء المخصصة

يمكنك إنشاء معالجات أخطاء مخصصة للتحكم في كيفية معالجة الأخطاء:

<?php // تعريف معالج أخطاء مخصص function customErrorHandler($errno, $errstr, $errfile, $errline) { $errorTypes = [ E_ERROR => 'خطأ', E_WARNING => 'تحذير', E_NOTICE => 'ملاحظة', E_USER_ERROR => 'خطأ مستخدم', E_USER_WARNING => 'تحذير مستخدم', E_USER_NOTICE => 'ملاحظة مستخدم' ]; $type = $errorTypes[$errno] ?? 'خطأ غير معروف'; // تسجيل الخطأ $message = "[$type] $errstr في $errfile على السطر $errline"; error_log($message); // عرض رسالة ودية للمستخدم echo "<div class='error'>حدث خطأ. يرجى المحاولة لاحقاً.</div>"; // للأخطاء الحرجة، أوقف التنفيذ if ($errno === E_ERROR || $errno === E_USER_ERROR) { die("خطأ حرج - تم إنهاء السكريبت"); } return true; // منع معالج الأخطاء الافتراضي في PHP } // تسجيل معالج الأخطاء المخصص set_error_handler('customErrorHandler'); // تشغيل أنواع مختلفة من الأخطاء trigger_error("هذه ملاحظة مستخدم", E_USER_NOTICE); trigger_error("هذا تحذير مستخدم", E_USER_WARNING); ?>

تشغيل الأخطاء المخصصة

يمكنك تشغيل أخطائك الخاصة باستخدام دالة trigger_error():

<?php function divideNumbers($dividend, $divisor) { if ($divisor == 0) { trigger_error("محاولة القسمة على صفر", E_USER_WARNING); return false; } return $dividend / $divisor; } $result = divideNumbers(10, 0); if ($result === false) { echo "فشلت العملية"; } ?>

عامل إخفاء الأخطاء

عامل @ يخفي رسائل الأخطاء، لكن استخدمه بحذر:

<?php // بدون إخفاء - يظهر تحذير $content = file_get_contents('nonexistent.txt'); // مع الإخفاء - لا يظهر تحذير $content = @file_get_contents('nonexistent.txt'); // نهج أفضل: فحص النتيجة $content = @file_get_contents('nonexistent.txt'); if ($content === false) { echo "تعذر قراءة الملف"; } ?>
نصيحة: بدلاً من إخفاء الأخطاء بـ @، من الأفضل فحص قيم الإرجاع ومعالجة الأخطاء بشكل صريح.

دالة الإغلاق

سجل دالة تعمل عند إنهاء السكريبت، مفيدة لالتقاط الأخطاء القاتلة:

<?php function shutdownHandler() { $error = error_get_last(); if ($error !== null && $error['type'] === E_ERROR) { // تسجيل الخطأ القاتل error_log("خطأ قاتل: " . $error['message']); // عرض رسالة ودية للمستخدم echo "<h1>عفواً! حدث خطأ ما</h1>"; echo "<p>نحن نعمل على إصلاح هذه المشكلة.</p>"; } } register_shutdown_function('shutdownHandler'); // كود التطبيق هنا ?>

أفضل الممارسات لمعالجة الأخطاء

<?php // 1. بيئة التطوير if ($_SERVER['SERVER_NAME'] === 'localhost') { error_reporting(E_ALL); ini_set('display_errors', 1); } else { // 2. بيئة الإنتاج error_reporting(E_ALL); ini_set('display_errors', 0); ini_set('log_errors', 1); ini_set('error_log', __DIR__ . '/logs/errors.log'); } // 3. تحقق دائماً من مدخلات المستخدم function processAge($age) { if (!is_numeric($age)) { trigger_error("العمر يجب أن يكون رقماً", E_USER_WARNING); return false; } if ($age < 0 || $age > 150) { trigger_error("العمر خارج النطاق الصحيح", E_USER_WARNING); return false; } return true; } // 4. فحص قيم إرجاع الدوال $file = fopen("data.txt", "r"); if ($file === false) { error_log("فشل فتح data.txt"); die("تعذر الوصول إلى الملف المطلوب"); } // 5. استخدم رسائل خطأ واضحة trigger_error("فشل الاتصال بقاعدة البيانات: بيانات اعتماد غير صحيحة", E_USER_ERROR); // وليس فقط: trigger_error("خطأ", E_USER_ERROR); ?>

تسجيل الأخطاء في ملف

<?php function logError($message, $level = 'ERROR') { $timestamp = date('Y-m-d H:i:s'); $logMessage = "[$timestamp] [$level] $message" . PHP_EOL; $logFile = __DIR__ . '/logs/app.log'; // إنشاء مجلد السجلات إذا لم يكن موجوداً $logDir = dirname($logFile); if (!is_dir($logDir)) { mkdir($logDir, 0755, true); } // إلحاق بملف السجل file_put_contents($logFile, $logMessage, FILE_APPEND); } // الاستخدام logError("فشلت مصادقة المستخدم", 'WARNING'); logError("فُقد الاتصال بقاعدة البيانات", 'CRITICAL'); logError("تم رفع الملف بنجاح", 'INFO'); ?>
تمرين:
  1. أنشئ معالج أخطاء مخصص يسجل الأخطاء في ملف مع الطوابع الزمنية
  2. اكتب دالة تقرأ ملف وتعالج أخطاء الملفات المفقودة بشكل صحيح
  3. أنشئ دالة تحقق تشغل الأخطاء المناسبة لعناوين البريد الإلكتروني غير الصحيحة
  4. قم بإعداد مستويات مختلفة للإبلاغ عن الأخطاء لبيئات التطوير والإنتاج

الأخطاء الشائعة التي يجب تجنبها

<?php // ❌ سيء: عرض الأخطاء في الإنتاج ini_set('display_errors', 1); // لا تفعل هذا أبداً في الإنتاج! // ✅ جيد: سجل الأخطاء، لا تعرضها ini_set('display_errors', 0); ini_set('log_errors', 1); // ❌ سيء: إخفاء جميع الأخطاء @include('config.php'); @$result = $dangerous_operation; // ✅ جيد: معالجة الأخطاء بشكل صريح if (file_exists('config.php')) { include('config.php'); } else { error_log('ملف الإعدادات مفقود'); die('خطأ في الإعدادات'); } // ❌ سيء: رسائل خطأ عامة trigger_error("خطأ", E_USER_ERROR); // ✅ جيد: رسائل خطأ وصفية trigger_error("فشل الاتصال بقاعدة البيانات: انتهت مهلة الاتصال", E_USER_ERROR); ?>
قائمة فحص الإنتاج:
  • أوقف عرض الأخطاء: display_errors = 0
  • فعّل تسجيل الأخطاء: log_errors = 1
  • حدد مسار سجل الأخطاء: error_log = /path/to/logs
  • أبلغ عن جميع الأخطاء: error_reporting = E_ALL
  • استخدم صفحات أخطاء مخصصة للأخطاء الظاهرة للمستخدم