معالجة الأخطاء (Error Handling) في Laravel

من موسوعة حسوب

مقدمة

عند بدء مشروع Laravel جديد تكون معالجة الأخطاء والاستثناءات مُعدّة لك مُسبقا. تُسجّل كافة الاستثناءات التي يطلقها تطبيقك في الصنف App\Exceptions\Handler ثم تُرجع للمُستخدم. سنتعمّق في هذا الصنف أكثر من خلال هذا التوثيق.

الضبط

يحدد الخيار debug في ملف إعداداتك config/app.php مقدار المعلومات الفعلية التي تُعرض عن الخطأ للمستخدم. يُعد هذا الاختيار إفتراضيًّا ليحترم قيمة متغيّر البيئة APP_DEBUG التي تُخزّن في ملفك env. .

عليك وضع قيمة متغير البيئة APP_DEBUG على true عند التطوير المحلّي. يجب أن توضع هذه القيمة دائمًا على false في بيئة إنتاجك. إذا وُضعت القيمة على true عند الإنتاج ستخاطر بفضح قيم ضبط حسّاسة لمستخدمي التطبيق النهائيين.

معالج الاستثناء

تابع التبليغ (The Report Method)

يعالج الصنف App\Exceptions\Handler كافة الاستثناءات. يحتوي هذا الصنف على تابعين: report و render. سنفحص كليهما بالتفصيل. يُستخدم التابع report لتسجيل (log) الاستثناءات أو لإرسالها لخدمة خارجية مثل Bugsnag أو Sentry. يمرر التابع report الاستثناء إلى الصنف الأساسي (base class) إفتراضيًّا حيث يُسجّل الاستثناء. لكنك تظل حرّا في تسجيل الاستثناءات كيفما تريد.

على سبيل المثال ، إذا كنت بحاجة للإبلاغ عن أنواع مختلفة من الاستثناءات بطرق مختلفة، تستطيع استخدام عامل (operator) مقارنة exampleof PHP:

/**
 * بلّغ أو سجّل إستثناءًا
 *  
 * Sentry, Bugsnag, etc هذا هو الموضع المثالي لإرسال الاستثناءات الى
 *
 * @param  \Exception  $exception
 * @return void
 */
public function report(Exception $exception)
{
    if ($exception instanceof CustomException) {
       //
    }

    return parent::report($exception);
}

ملاحظة: بدل الإكثار من استخدام instanceof للتفقّد في تابعك report، ضع استخدام الاستثناءات القابلة للتبليغ بالحسبان.

المُساعد report

قد تحتاج في بعض الأحيان إلى التبليغ عن استثناء ولكن مع متابعة معالجة الطلب الحالي. تتيح لك دالّة مساعد التبليغ report البانية التبليغ عن الاستثناء بسرعة باستخدام تابع معالج استثنائك report دون عرض صفحة خطأ:

public function isValid($value)
{
    try {
       // تحقق من القيمة ....
    } catch (Exception $e) {
        report($e);

        return false;
    }
}

تجاهل الاستثناءات حسب النوع

تحتوي الخاصية dontReport$ لمُعالج الاستثناء على مصفوفة من أنواع الاستثناء التي لن تُسجّل. على سبيل المثال، لا تُكتب الاستثناءات الناتجة عن أخطاء 404، إضافة إلى العديد من أنواع الأخطاء الأخرى في ملفات سجلّك. يمكنك إضافة أنواع استثناءات أخرى لهذه المصفوفة حسب الحاجة:

/**
 * قائمة أنواع الاستثناءات التي لا يجب الإبلاغ عنها.
 *
 * @var array
 */
protected $dontReport = [
    \Illuminate\Auth\AuthenticationException::class,
    \Illuminate\Auth\Access\AuthorizationException::class,
    \Symfony\Component\HttpKernel\Exception\HttpException::class,
    \Illuminate\Database\Eloquent\ModelNotFoundException::class,
    \Illuminate\Validation\ValidationException::class,
];

تابع التصيير (The Render Method)

يعتبر التابع render مسؤولا عن تحويل أي استثناء معيّن إلى رد HTTP يجب ردّه للمُتصفّح (browser). يُمرّر الاستثناء إلى الصنف الأساسي الذي يُولّد ردّا نيابة عنك إفتراضيًّا. تظل حرّا مع ذلك في التحقق من نوع الاستثناء أو في إعادة رد خاص بك:

/**
 *  HTTP صيّر استثناءا لردّ 
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $exception
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $exception)
{
    if ($exception instanceof CustomException) {
        return response()->view('errors.custom', [], 500);
    }

    return parent::render($request, $exception);
}

الاستثناءات القابلة للتبليغ والقابلة للتصيير

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

<?php

namespace App\Exceptions;

use Exception;

class RenderException extends Exception
{
    /**
     * Report the exception.
     *
     * @return void
     */
    public function report()
    {
       //
    }

    /**
     * Render the exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request
     * @return \Illuminate\Http\Response
     */
    public function render($request)
    {
        return response(...);
    }
}

الاستثناءات HTTP

تصف بعض الاستثناءات رموز خطأ HTTP من الخادم. قد يكون هذا مثلا خطأ "لم يُعثر على الصفحة" (404) ، أو "خطأ غير مُخوّل" (401) أو حتى أخطاء يُولّدها المُطوّر 500. كي تُولّد هذا النوع من الاستجابة من أي مكان في تطبيقك، يمكنك استخدام المُساعد abort:

abort(404);

سيُطلق المساعد abort مباشرةً استثناءًا يُصيّره (render) معالج الاستثناء. لديك خيار تقديم نص الاستجابة بنفسك:

abort(403, 'Unauthorized action.');

صفحات الخطأ HTTP المخصّصة (Custom HTTP Error Pages)

يُسهّل Laravel عرض صفحات الخطأ المخصّصة لعدّة رموز حالة HTTP مُتنوّعة. مثلا، إن رغبت في تخصيص (customize) صفحة الخطأ لرمز الحالة HTTP 404، أنشئ resources/views/errors/404.blade.php. سيُقدّم هذا الملف مع كافّة الأخطاء 404 التي يُولّدها تطبيقك. يجب تسمية الواجهات (views) داخل هذا المجلّد بحيث تتطابق مع رمز الحالة HTTP الذي تقابله. ستُمرّر النسخة HttpException التي أطلقتها الدالّة البانية abort للواجهة (view) كمتغيّر exception$:

<h2>{{ $exception->getMessage() }}</h2>

مصادر