رسیدگی به خطا
معرفی
هنگامی که یک پروژه جدید لاراول را شروع می کنید، مدیریت خطا و استثنا از
قبل برای شما پیکربندی شده است. کلاس
App\Exceptions\Handler
جایی است که تمام استثناهای پرتاب شده توسط برنامه شما ثبت شده و سپس به
کاربر ارائه می شود. ما در طول این مستندات عمیقتر به این کلاس خواهیم پرداخت.
پیکربندی
گزینه
debug
موجود در
config/app.php
فایل پیکربندی شما تعیین می کند که واقعاً چه مقدار اطلاعات در مورد یک خطا
به کاربر نمایش داده می شود. به طور پیش فرض، این گزینه به گونه ای تنظیم شده است که به مقدار
APP_DEBUG
متغیر محیطی که در فایل شما ذخیره می شود، احترام بگذارد
.env
.
در طول توسعه محلی، باید
APP_DEBUG
متغیر محیطی را روی
true
.
در محیط تولید شما، این مقدار باید همیشه باشد
false
. اگر مقدار
true
در مرحله تولید تنظیم شده باشد، در معرض خطر قرار دادن مقادیر حساس
پیکربندی برای کاربران نهایی برنامه خود هستید.
کنترل کننده استثنا
استثناهای گزارش دهی
همه استثناها توسط
App\Exceptions\Handler
کلاس انجام می شود. این کلاس حاوی
register
روشی است که در آن میتوانید گزارشهای استثنایی سفارشی را ثبت کنید و
پاسخهای تماس را ارائه کنید. هر یک از این مفاهیم را به تفصیل بررسی خواهیم کرد. گزارش استثنا برای ثبت
استثناها یا ارسال آنها به یک سرویس خارجی مانند
Flare
،
Bugsnag
یا
Sentry
استفاده می شود . به طور پیش فرض، استثناها بر اساس پیکربندی
ورود به
سیستم شما ثبت می شوند
. با این حال، شما آزاد هستید که استثناها را هر طور که می خواهید ثبت کنید.
برای مثال، اگر نیاز دارید انواع مختلف استثناها را به روشهای مختلف گزارش
کنید، میتوانید از
reportable
روشی برای ثبت یک بسته استفاده کنید که باید در زمانی که استثنایی از یک نوع
معین باید گزارش شود، اجرا شود. لاراول با بررسی نوع اشاره بسته استنباط میکند که بسته شدن چه نوع استثنایی را
گزارش میکند:
use App\Exceptions\InvalidOrderException; /** * Register the exception handling callbacks for the application. * * @return void */public function register(){ $this->reportable(function (InvalidOrderException $e) { // });}
هنگامی که با استفاده از این متد، یک استثنای سفارشی را ثبت میکنید
reportable
، لاراول همچنان استثنا را با استفاده از پیکربندی پیشفرض گزارشگیری برای
برنامه ثبت میکند. اگر میخواهید انتشار استثنا در پشته گزارش پیشفرض را متوقف کنید، میتوانید
stop
هنگام تعریف پاسخ به تماس گزارشی خود یا بازگشت
false
از پاسخ به تماس از این روش استفاده کنید:
$this->reportable(function (InvalidOrderException $e) { //})->stop(); $this->reportable(function (InvalidOrderException $e) { return false;});
برای سفارشی کردن گزارش استثنا برای یک استثنا خاص، میتوانید از استثناهای قابل گزارش نیز استفاده کنید .
زمینه ثبت جهانی
اگر در دسترس باشد، لاراول به طور خودکار شناسه کاربر فعلی را به عنوان داده
های متنی به پیام گزارش هر استثنا اضافه می کند. شما می توانید داده های متنی جهانی خود را با نادیده گرفتن
context
روش کلاس برنامه خود تعریف کنید
App\Exceptions\Handler
. این اطلاعات در هر پیام گزارش استثنایی که توسط برنامه شما نوشته شده است
گنجانده می شود:
/** * Get the default context variables for logging. * * @return array */protected function context(){ return array_merge(parent::context(), [ 'foo' => 'bar', ]);}
متن گزارش استثنا
در حالی که افزودن زمینه به هر پیام گزارش می تواند مفید باشد، گاهی اوقات
یک استثنا خاص ممکن است زمینه منحصر به فردی داشته باشد که شما بخواهید آن را در گزارش های خود بگنجانید. با
تعریف
context
روشی در یکی از استثناهای سفارشی برنامه خود، میتوانید هر داده مرتبط با آن
استثنا را که باید به ورودی گزارش استثنا اضافه شود، مشخص کنید:
<?php namespace App\Exceptions; use Exception; class InvalidOrderException extends Exception{ // ... /** * Get the exception's context information. * * @return array */ public function context() { return ['order_id' => $this->orderId]; }}
یاور
report
_
گاهی اوقات ممکن است لازم باشد یک استثنا را گزارش کنید اما به رسیدگی به
درخواست فعلی ادامه دهید. تابع
helper
report
به شما امکان می دهد تا به سرعت یک استثنا را از طریق کنترل کننده استثنا
بدون ارائه صفحه خطا به کاربر گزارش دهید:
public function isValid($value){ try { // Validate the value... } catch (Throwable $e) { report($e); return false; }}
سطوح ثبت استثنا
وقتی پیامها در گزارشهای برنامه شما نوشته میشوند ، پیامها در سطح گزارش مشخصی نوشته میشوند ، که نشاندهنده شدت یا اهمیت پیام ثبتشده است.
همانطور که در بالا ذکر شد، حتی زمانی که با استفاده از این روش، یک استثنا
سفارشی را ثبت میکنید
reportable
، لاراول همچنان استثنا را با استفاده از پیکربندی پیشفرض گزارشگیری برای
برنامه ثبت میکند. با این حال، از آنجایی که سطح گزارش گاهی اوقات میتواند بر کانالهایی که یک پیام در آنها
ثبت میشود تأثیر بگذارد، ممکن است بخواهید سطح گزارشی را پیکربندی کنید که استثناهای خاصی در آن ثبت شوند.
برای انجام این کار، میتوانید آرایهای از انواع استثنا و سطوح گزارش مربوط
به آنها را در
$levels
ویژگی کنترلکننده استثنای برنامه خود تعریف کنید:
use PDOException;use Psr\Log\LogLevel; /** * A list of exception types with their corresponding custom log levels. * * @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*> */protected $levels = [ PDOException::class => LogLevel::CRITICAL,];
نادیده گرفتن استثناها بر اساس نوع
هنگام ساخت برنامه خود، برخی از انواع استثناها وجود دارد که به سادگی می
خواهید نادیده بگیرید و هرگز گزارش نکنید. کنترل کننده استثنای برنامه شما حاوی
$dontReport
ویژگی است که به یک آرایه خالی مقدار دهی اولیه می شود. هر کلاسی که به این
ویژگی اضافه کنید هرگز گزارش نخواهد شد. با این حال، ممکن است هنوز منطق رندر سفارشی داشته باشند:
use App\Exceptions\InvalidOrderException; /** * A list of the exception types that are not reported. * * @var array<int, class-string<\Throwable>> */protected $dontReport = [ InvalidOrderException::class,];
در پشت صحنه، لاراول قبلاً برخی از انواع خطاها را برای شما نادیده می گیرد، مانند استثناهای ناشی از خطاهای 404 HTTP «نیافتن» یا 419 پاسخ HTTP تولید شده توسط توکن های نامعتبر CSRF.
رندر استثناها
به طور پیش فرض، کنترل کننده استثنا لاراول استثناها را به یک پاسخ HTTP
برای شما تبدیل می کند. با این حال، شما آزاد هستید که یک بسته رندر سفارشی را برای استثناهایی از یک نوع مشخص
ثبت کنید. شما می توانید این کار را از طریق
renderable
روش کنترل کننده استثنای خود انجام دهید.
بسته شدن ارسال شده به
renderable
متد باید یک نمونه از را برگرداند
Illuminate\Http\Response
که ممکن است از طریق
response
کمک کننده ایجاد شود. لاراول با بررسی نوع اشاره بسته استنباط می کند که
بسته شدن چه نوع استثنایی را ارائه می دهد:
use App\Exceptions\InvalidOrderException; /** * Register the exception handling callbacks for the application. * * @return void */public function register(){ $this->renderable(function (InvalidOrderException $e, $request) { return response()->view('errors.invalid-order', [], 500); });}
همچنین می توانید از این
renderable
روش برای نادیده گرفتن رفتار رندر برای استثناهای داخلی لاراول یا سیمفونی
مانند
NotFoundHttpException
. اگر بسته شدن داده شده به
renderable
متد مقداری را برنگرداند، از رندر استثنایی پیشفرض لاراول استفاده میشود:
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Register the exception handling callbacks for the application. * * @return void */public function register(){ $this->renderable(function (NotFoundHttpException $e, $request) { if ($request->is('api/*')) { return response()->json([ 'message' => 'Record not found.' ], 404); } });}
استثناهای قابل گزارش و اجرا
به جای استثناهای بررسی نوع در
register
روش کنترل کننده استثنا، می توانید
مستقیماً استثناهای سفارشی خود را تعریف
report
و متد کنید.
render
هنگامی که این متدها وجود داشته باشند، به طور خودکار توسط فریمورک فراخوانی
می شوند:
<?php namespace App\Exceptions; use Exception; class InvalidOrderException extends Exception{ /** * Report the exception. * * @return bool|null */ public function report() { // } /** * Render the exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function render($request) { return response(/* ... */); }}
اگر استثنای شما استثنایی را گسترش دهد که از قبل قابل اجرا است، مانند یک
استثنای داخلی لاراول یا Symfony، میتوانید
false
از متد استثنا
render
برای ارائه پاسخ HTTP پیشفرض استثنا برگردید:
/** * Render the exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */public function render($request){ // Determine if the exception needs custom rendering... return false;}
اگر استثنای شما حاوی منطق گزارش دهی سفارشی است که فقط زمانی لازم است که
شرایط خاصی برآورده شود، ممکن است لازم باشد به لاراول دستور دهید که گاهی استثنا را با استفاده از پیکربندی پیش
فرض مدیریت استثنا گزارش دهد. برای انجام این کار، می توانید
false
از روش استثنا برگردید
report
:
/** * Report the exception. * * @return bool|null */public function report(){ // Determine if the exception needs custom reporting... return false;}
میتوانید وابستگیهای مورد نیاز متد را تایپ کنید و آنها به طور خودکار توسط کانتینر سرویس
report
لاراول به متد تزریق میشوند .
استثناهای HTTP
برخی استثناها کدهای خطای HTTP را از سرور توصیف می کنند. به عنوان مثال،
این ممکن است یک خطای "صفحه یافت نشد" (404)، یک "خطای غیرمجاز" (401) یا حتی یک خطای 500 توسط توسعه دهنده
باشد. برای ایجاد چنین پاسخی از هر نقطه در برنامه خود، می توانید از
abort
راهنما استفاده کنید:
abort(404);
صفحات خطای سفارشی HTTP
لاراول نمایش صفحات خطای سفارشی برای کدهای وضعیت HTTP مختلف را آسان می
کند. به عنوان مثال، اگر می خواهید صفحه خطا را برای کدهای وضعیت HTTP 404 سفارشی کنید، یک
resources/views/errors/404.blade.php
الگوی نمایش ایجاد کنید. این نما روی تمام خطاهای 404 ایجاد شده توسط برنامه
شما ارائه می شود. نماهای موجود در این فهرست باید به گونه ای نامگذاری شوند که با کد وضعیت HTTP مطابقت دارند.
نمونه
ای
Symfony\Component\HttpKernel\Exception\HttpException
که توسط
abort
تابع مطرح می شود به عنوان یک متغیر به view ارسال می شود
$exception
:
<h2>{{ $exception->getMessage() }}</h2>
شما می توانید قالب های صفحه خطای پیش فرض لاراول را با استفاده از
vendor:publish
دستور Artisan منتشر کنید. پس از انتشار قالب ها، می توانید آنها را به
دلخواه شخصی سازی کنید:
php artisan vendor:publish --tag=laravel-errors
صفحات خطای بازگشتی HTTP
همچنین میتوانید برای یک سری کدهای وضعیت HTTP یک صفحه خطای «بازگشت» تعریف
کنید. اگر صفحه مربوط به کد وضعیت HTTP خاصی که رخ داده وجود نداشته باشد، این صفحه نمایش داده می شود. برای
انجام این کار، یک
4xx.blade.php
الگو و یک
5xx.blade.php
الگو را در فهرست برنامه خود تعریف کنید
resources/views/errors
.