مقدمة: لماذا معالجة الأخطاء الأساسية هي مجرد البداية
كل مطور PHP يعرف بنية try/catch. ولكن عندما ينمو المشروع إلى آلاف الأسطر من الكود، ويصبح الحمل على الخادم مرتفعًا، فإن مجرد التقاط الاستثناءات لا يكفي. معالجة الأخطاء المتقدمة ليست مجرد "التقط وانسى"، بل هي نظام كامل: من تسجيل الأخطاء إلى تحويل التحذيرات إلى استثناءات.
في هذه المقالة، سنستعرض التقنيات التي ستساعدك على كتابة كود موثوق ومتحمل للأخطاء: كتل catch المتعددة، فئات الاستثناءات المخصصة، المعالجات العامة، والتكامل مع مسجلات PSR-3. المادة موجهة للمطورين الذين لديهم معرفة أساسية بـ PHP.
1. كتل catch المتعددة وترتيب الاستثناءات
بدءًا من PHP 7.1، يمكنك التقاط أنواع مختلفة من الاستثناءات في كتلة try واحدة. هذا يسمح بالاستجابة بدقة للأخطاء:
<?phpclass DatabaseException extends \\Exception {}class ValidationException extends \\Exception {}
try { // كود قد يرمي استثناءات مختلفة $user = $db->query('SELECT ...'); if (!$user) { throw new DatabaseException('خطأ في الاستعلام'); } if (empty($user['email'])) { throw new ValidationException('البريد الإلكتروني مطلوب'); }} catch (DatabaseException $e) { // تسجيل خطأ قاعدة البيانات error_log('DB Error: ' . $e->getMessage()); echo 'خطأ مؤقت في الخادم. حاول مرة أخرى لاحقًا.';} catch (ValidationException $e) { // عرض رسالة مفهومة للمستخدم echo 'خطأ: ' . htmlspecialchars($e->getMessage());} catch (\\Throwable $e) { // التقاط كل شيء آخر (بما في ذلك Error) error_log('Critical: ' . $e->getMessage()); echo 'خطأ حرج.';}?>لماذا هذا مهم؟ كل نوع من الاستثناءات يتطلب رد فعل مختلف. خطأ قاعدة البيانات - إخفاء التفاصيل عن المستخدم، خطأ التحقق - عرض النموذج مع تمييز الحقل، الخطأ الحرج - إرسال إشعار للمسؤول.
لاحظ استخدام \\Throwable - وهي واجهة تنفذها كل من Exception و Error (الأخطاء الفادحة في PHP). استخدمها في آخر كتلة catch لضمان عدم تفويت أي خطأ.
2. فئات الاستثناءات المخصصة: توسيع المعايير
توفر الفئة القياسية \\Exception وظائف أساسية. ولكن في المشاريع الحقيقية، من المفيد إنشاء تسلسلات هرمية خاصة بك للاستثناءات - وهذا يبسط التصحيح والمعالجة.
مثال على هيكل لتطبيق ويب:
<?phpnamespace App\\Exceptions;
// الاستثناء الأساسي للتطبيقclass AppException extends \\RuntimeException{ protected $context = [];
public function __construct(string $message = '', int $code = 0, ?\\Throwable $previous = null, array $context = []) { parent::__construct($message, $code, $previous); $this->context = $context; }
public function getContext(): array { return $this->context; }}
// استثناء لأخطاء HTTPclass HttpException extends AppException{ private int $statusCode;
public function __construct(int $statusCode, string $message = '', array $context = []) { $this->statusCode = $statusCode; parent::__construct($message, $statusCode, null, $context); }
public function getStatusCode(): int { return $this->statusCode; }}
// الاستخدامthrow new HttpException(404, 'الصفحة غير موجودة', ['uri' => $_SERVER['REQUEST_URI']]);?>المزايا:
- يمكن تمرير سياق إضافي (معلمات الطلب، معرف المستخدم) - وهذا يبسط تسجيل الأخطاء.
- يتم تجميع الاستثناءات حسب المعنى:
HttpException،ValidationException،PaymentException.