يستخدم Laravel الصنف Handler
الموجود على المسار app/Exceptions
للتعامل مع جميع الاستثناءات. يحوي هذا الصّنف دالتين: report
وrender
. تُستخدَم دالة report
لتسجيل الاستثناءات أو إرسالها إلى خدمة خارجية؛ أما الدالة render
فتُستخدَم لاعتراض الاستثناءات وإرسال إجابة مناسبة إلى المتصفّح ليعرضها للزّائر.
ملحوظة: اعتمدنا العروض، المسارات والمتحكّم الذي أنشأناه في درس كيف تستخدم PHPUnit لاختبار تطبيقات Laravel وبنينا عليها لتطبيق الخطوات الواردة هنا. يمكنك تجربة الدّرس على مشروعك الخاص أو استخدام الملفّ المرفَق الذي يمثّل الحصيلة النهائية لهذا الدرس. إن استخدمت الملفّ المرفق فستحتاج لتسجيل مستخدم أولا عبر رابط register
والدخول إلى الموقع حتى يظهر بقية المحتوى (سنترك لك اكتشاف الآلية المستخدمة في ذلك. كلمة السّر: المسارات المحميّة).
تخصيص رسائل الاستثناءات
يُعدّ ErrorException
أحد أكثر الاستثناءات انتشارا ويظهر مثلا عند إضافة معرف كائن غير موجود إلى مسار URL، أو عند طلب خاصيّة غير موجودة في الكائن. عند محاولة دخول المسار التالي دون أن تكون التسجيلة ذات المعرّف 56
موجودة في جدول البيانات widgets
:
laravel.dev/widget/56
فستظهر في المتصفّح صفحة خطأ كالتالي:
صفحة الخطأ هذه مفيدة للمطوّرين إلا أننا لا نرغب في أن يراها زوار الموقع؛ لذا يجب علينا التعامل مع هذا الاستثناء وقت حدوثه وعرض رسالة مغايرة للزائر.
نعدّل دالة render
في ملف Handler.php
لتصبِح على النحو التالي:
public function render($request, Exception $e) { switch($e){ case ($e instanceof ErrorException): return $this->ErrorException($e); break default: return parent::render($request, $e); } }
ثم نضيف الدالة التالية إلى الملف:
protected function renderErrorException($e) { return response()->view('errors.404', [], 404);/* }
يمكنك أن تلاحظ أننا أضفنا عبارة switch
إلى الدالة من أجل تحديد نوعيّة الاستثناء فإن كان من نوع ErrorException
استدعينا الدالة renderErrorException
وإلا نترك الدالة المبدئية تتكفّل بالموضوع. استخدمنا عبارة switch
هنا لتسهيل إضافة معالَجات خاصّة في ما بعد لأنواع أخرى من الاستثناءات.
نستخدم في الدالة renderErrorException
عرضا خاصّا سميناه 404
. يحوي مجلد العروض في Laravel مجلّدا خاصّا لعروض الأخطاء errors
؛ ننشئ فيه العرض 404
ذي المحتوى التالي مع إضافة اللاحقة blade.php.
:
@extends('layouts.app') @section('content') <div class="alert alert-danger alert-dismissible alert-important" role="alert"> <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button> <strong>Oh Snap!</strong> We can't find what you are looking for... </div> @endsection
بقي لنا استيراد صنف الاستثناءات ErrorException
في ملف Handler.php
:
use ErrorException;
هذا كل ما نحتاجه. نعود الآن لنرى الرابط السابق:
laravel.dev/widget/56
إن لم يكن الكائن ذو المعرّف موجودا فستظهر رسالة الخطأ التالية:
تخصيص الاستثناءات
استخدمنا في الفقرة السابقة استثناءً موجودا وخصّصنا النتيجة التي يعرضها للزائر. نريد في هذه الفقرة إنشاء استثناء مخصَّص لتلبية حاجة خاصّة بمشروعنا. سنفرض مثلا أننا نريد إظهار رسالة خطأ للزائر عند تصفّح الرابط /create/widget/
، سنسمّي الاستثناء الجديد WidgetCreateException
.
نبدأ بإنشاء ملف WidgetCreateException.php
في المجلّد Exceptions
:
<?php namespace App\Exceptions; class WidgetCreateException extends \Exception { }
لاحظ مساحة الأسماء Namespace. لا نريد أن نعقّد الأمور، لذا سنترك الصّنف على ماهو عليه دون إضافة معالجات خاصّة، حتى نفهم المبدأ.
نعود للملف Handler.php
ونعدّله باستيراد الصّنف الذي أنشأناه للتّو:
use App\Exceptions\WidgetCreateException;
ثم نعدّل دالّة render
كالتالي:
public function render($request, Exception $e) { switch($e) { case ($e instanceof ErrorException): return $this->renderErrorException($e); break; case ($e instanceof WidgetCreateException): return $this->renderWidgetCreateException($e); break; default: return parent::render($request, $e); } }
ونضيف أيضا الدالة التالية:
protected function renderWidgetCreateException($e) { return response()->view('errors.widgetcreate', [], 404); }
يعني هذا أنه في حالة ظهور استثناء من نوع WidgetCreateException
فسنستدعي الدالة renderWidgetCreateException
التي تُظهر العرض widgetcreate
.
بقي لنا الآن إنشاء ملف العرض widgetcreate.blade.php
في المجلّد errors
التابع لمجلد العروض:
@extends('layouts.app') @section('content') <div class="alert alert-danger alert-dismissible alert-important" role="alert"> <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button> <strong>Yes!</strong> You threw a Widget Creation Exception... </div> @endsection
سننشئ لتجربة صنف الاستثناء الجديد داالةً في المتحكّم المناسب (HomeController
في حالتي) كما يلي:
public function create() { throw new WidgetCreateException; }
لا تنس استيراد الصنف WidgetCreateException
في المتحكم:
use App\Exceptions\WidgetCreateException;
وإضافة مسار لـ/create/widget
في ملف routes.php
:
Route::group(['middleware' => 'web'], function () { Route::auth(); Route::get('/create/widget', 'HomeController@create'); });
نجرّب عمل الاستثناء بزيارة المسار التالي:
http://laranew.dev/create/widget
لاحظ النتيجة:
قدّمنا في هذا المقال أساسيات تخصيص الاستثناءات في Laravel؛ ما زال يوجد الكثير لتعلمّه في هذا الإطار انطلاقا من هذه الأساسيات.
حمل الملف المرفق لهذا الدرس.
ترجمة -وبتصرّف- للمقال Handling Exceptions and Custom Exceptions in Laravel 5.1 لصاحبه Bill Keck.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.