在本文中,我们将探讨 Laravel Web 框架中最重要且讨论最少的特性之一——异常处理。Laravel 带有一个内置的异常处理程序,允许您以友好的方式轻松报告和呈现异常。
在本文的前半部分,我们将探讨异常处理程序提供的默认设置。事实上,我们将首先通过默认的 Handler 类来了解 Laravel 如何处理异常。
在本文的后半部分,我们将继续了解如何创建自定义异常处理程序,以允许您捕获自定义异常。
设置先决条件
在我们直接深入处理程序类之前,让我们看一下与异常相关的几个重要配置参数。
继续并打开config/app.php文件。让我们仔细看看下面的代码片段。
... /* |-------------------------------------------------------------------------- | Application Debug Mode |-------------------------------------------------------------------------- | | When your application is in debug mode, detailed error messages with | stack traces will be shown on every error that occurs within your | application. If disabled, a simple generic error page is shown. | */ 'debug' => (bool) env('APP_DEBUG', false), ... ...
顾名思义,如果设置为TRUE
,它将帮助您调试应用程序生成的错误。此变量的默认值设置为.env文件中APP_DEBUG
环境变量的值。
在开发环境中,您应该将其设置为,TRUE
以便您可以轻松跟踪错误并修复它们。另一方面,您想在生产环境中将其关闭,在这种情况下它将显示一个通用错误页面。
日志记录配置文件
除了显示错误,Laravel 还允许你在日志文件中记录错误。让我们快速浏览一下可用于记录的选项。让我们访问config/logging.php文件并仔细查看以下代码段。
<?php use Monolog\Handler\NullHandler; use Monolog\Handler\StreamHandler; use Monolog\Handler\SyslogUdpHandler; return [ /* |-------------------------------------------------------------------------- | Default Log Channel |-------------------------------------------------------------------------- | | This option defines the default log channel that gets used when writing | messages to the logs. The name specified in this option should match | one of the channels defined in the "channels" configuration array. | */ 'default' => env('LOG_CHANNEL', 'stack'), /* |-------------------------------------------------------------------------- | Log Channels |-------------------------------------------------------------------------- | | Here you may configure the log channels for your application. Out of | the box, Laravel uses the Monolog PHP logging library. This gives | you a variety of powerful log handlers / formatters to utilize. | | Available Drivers: "single", "daily", "slack", "syslog", | "errorlog", "monolog", | "custom", "stack" | */ 'channels' => [ 'stack' => [ 'driver' => 'stack', 'channels' => ['single'], 'ignore_exceptions' => false, ], 'single' => [ 'driver' => 'single', 'path' => storage_path('logs/laravel.log'), 'level' => 'debug', ], 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), 'level' => 'debug', 'days' => 14, ], 'slack' => [ 'driver' => 'slack', 'url' => env('LOG_SLACK_WEBHOOK_URL'), 'username' => 'Laravel Log', 'emoji' => ':boom:', 'level' => 'critical', ], 'papertrail' => [ 'driver' => 'monolog', 'level' => 'debug', 'handler' => SyslogUdpHandler::class, 'handler_with' => [ 'host' => env('PAPERTRAIL_URL'), 'port' => env('PAPERTRAIL_PORT'), ], ], 'stderr' => [ 'driver' => 'monolog', 'handler' => StreamHandler::class, 'formatter' => env('LOG_STDERR_FORMATTER'), 'with' => [ 'stream' => 'php://stderr', ], ], 'syslog' => [ 'driver' => 'syslog', 'level' => 'debug', ], 'errorlog' => [ 'driver' => 'errorlog', 'level' => 'debug', ], 'null' => [ 'driver' => 'monolog', 'handler' => NullHandler::class, ], 'emergency' => [ 'path' => storage_path('logs/laravel.log'), ], ], ];
Laravel 日志记录基于通道。每个通道都提供了不同的方式来写入日志信息。例如,single
通道将日志写入日志文件,slack
通道用于将日志发送到 Slack 以通知您的团队。由于 Laravel 使用 Monolog PHP 库进行日志记录,您应该在该库的上下文中设置上述选项。默认情况下,Laravel 使用stack
通道来记录消息。
默认日志文件位于storage/logs/laravel.log,在大多数情况下就足够了。另一方面,level
通道配置中的属性设置为一个值,该值指示将记录的错误的严重性。
Handler
班级_
接下来,我们来看看Handler
默认 Laravel 应用程序自带的默认类。继续打开app/Exceptions/Handler.php文件。
<?php namespace App\Exceptions; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Throwable; class Handler extends ExceptionHandler { /** * A list of the exception types that are not reported. * * @var array */ protected $dontReport = [ // ]; /** * A list of the inputs that are never flashed for validation exceptions. * * @var array */ protected $dontFlash = [ 'password', 'password_confirmation', ]; /** * Report or log an exception. * * @param \Throwable $exception * @return void * * @throws \Throwable */ public function report(Throwable $exception) { parent::report($exception); } /** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Throwable $exception * @return \symfony\Component\HttpFoundation\Response * * @throws \Throwable */ public function render($request, Throwable $exception) { return parent::render($request, $exception); } }
处理程序类负责两个重要的功能——报告和呈现所有错误。
让我们仔细看看report
方法。
/** * Report or log an exception. * * @param \Throwable $exception * @return void * * @throws \Throwable */ public function report(Throwable $exception) { parent::report($exception); }
该report
方法用于将错误记录到日志文件中。同时,注意该dontReport
属性也很重要,它列出了不应记录的所有类型的异常。
接下来,我们引入render
方法。
/** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Throwable $exception * @return \Symfony\Component\HttpFoundation\Response * * @throws \Throwable */ public function render($request, Throwable $exception) { return parent::render($request, $exception); }
如果该report
方法用于记录或报告错误,则该render
方法用于在屏幕上呈现错误。事实上,这个方法处理异常发生时将向用户显示的内容。
该render
方法还允许您为不同类型的异常自定义响应,我们将在下一节中看到。
自定义异常类
在本节中,我们将创建一个自定义异常类来处理该CustomException
类型的异常。创建自定义异常类背后的想法是轻松管理自定义异常并同时呈现自定义响应。
继续创建一个包含以下内容的文件app/Exceptions/CustomException.php 。
<?php namespace App\Exceptions; use Exception; class CustomException 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()->view( 'errors.custom', array( 'exception' => $this ) ); } }
这里要注意的重要一点是CustomException
该类必须扩展核心Exception
类。出于演示目的,我们只讨论render
方法,当然您也可以自定义报告方法。
如您所见,errors.custom
在我们的案例中,我们将用户重定向到错误页面。这样,您可以为特定类型的异常实现自定义错误页面。
当然,我们需要在resources/views/errors/custom.blade.php创建一个关联的视图文件。
Exception details: <b>{{ $exception->getMessage() }}</b>
这是一个显示错误消息的非常简单的视图文件,但您当然可以按照您想要的方式设计它。
我们还需要修改app/Exceptions/Handler.php文件的 render 方法,以便调用我们的自定义异常类。让我们在app/Exceptions/Handler.php文件中将render
方法替换为以下内容。
/** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Throwable $exception * @return \Symfony\Component\HttpFoundation\Response * * @throws \Throwable */ public function render($request, Throwable $exception) { if ($exception instanceof \App\Exceptions\CustomException) { return $exception->render($request); } return parent::render($request, $exception); }
如您所见,我们首先在 render 方法中检查异常的类型。如果异常的类型是\App\Exceptions\CustomException
,我们调用render
该类的方法。
如何测试我们的CustomException
班级
所以现在一切就绪。接下来,让我们继续在app/Http/Controllers/ExceptionController.php中创建一个控制器文件,以便我们可以测试我们的自定义异常类。
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; class ExceptionController extends Controller { public function index() { // something went wrong and you want to throw CustomException throw new \App\Exceptions\CustomException('Something Went Wrong.'); } }
当然,您需要在routes/web.php中添加关联的路由,如下面的代码片段所示。
// Exception routes Route::get('exception/index', 'ExceptionController@index');
有了它,您可以访问https://your-laravel-site.com/exception/index URL 以查看它是否按预期工作。它应该errors.custom
根据我们的配置显示视图。
这就是如何在 Laravel 中处理自定义异常。
结论
今天,我们了解了 Laravel 中的异常处理功能。在文章的开头,我们探索了 Laravel 提供的基本配置,以便渲染和报告异常。此外,我们简要了解了默认异常处理程序类。
- 日志记录配置文件
- Handler班级_
- 如何测试我们的CustomException班级