Skip to content
赞助商
虚位以待
赞助商
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待

错误与日志

介绍

当你开始一个新的 Laravel 项目时,错误和异常处理已经为你配置好了。App\Exceptions\Handler 类是所有由你的应用程序触发的异常被记录并渲染回用户的地方。我们将在本文档中更深入地探讨这个类。

对于日志记录,Laravel 使用 Monolog 库,它提供了对多种强大日志处理器的支持。Laravel 为你配置了其中的几个处理器,允许你在单个日志文件、旋转日志文件或将错误信息写入系统日志之间进行选择。

配置

错误详情

config/app.php 配置文件中的 debug 选项决定了向用户显示多少错误信息。默认情况下,此选项设置为遵循存储在 .env 文件中的 APP_DEBUG 环境变量的值。

对于本地开发,你应该将 APP_DEBUG 环境变量设置为 true。在生产环境中,此值应始终为 false。如果在生产中将此值设置为 true,你可能会将敏感的配置值暴露给应用程序的终端用户。

日志存储

Laravel 开箱即支持将日志信息写入 single 文件、daily 文件、syslogerrorlog。要配置 Laravel 使用哪种存储机制,你应该修改 config/app.php 配置文件中的 log 选项。例如,如果你希望使用每日日志文件而不是单个文件,你应该将 app 配置文件中的 log 值设置为 daily

php
'log' => 'daily'

最大每日日志文件

使用 daily 日志模式时,Laravel 默认只保留五天的日志文件。如果你想调整保留文件的数量,可以在 app 配置文件中添加一个 log_max_files 配置值:

php
'log_max_files' => 30

日志严重级别

使用 Monolog 时,日志消息可能具有不同的严重级别。默认情况下,Laravel 将所有日志级别写入存储。然而,在生产环境中,你可能希望通过在 app.php 配置文件中添加 log_level 选项来配置应记录的最低严重级别。

一旦配置了此选项,Laravel 将记录所有大于或等于指定严重级别的日志。例如,默认的 log_levelerror 将记录 errorcriticalalertemergency 消息:

php
'log_level' => env('APP_LOG_LEVEL', 'error'),

NOTE

Monolog 识别以下严重级别 - 从最不严重到最严重:debuginfonoticewarningerrorcriticalalertemergency

自定义 Monolog 配置

如果你希望完全控制 Monolog 在你的应用程序中的配置,可以使用应用程序的 configureMonologUsing 方法。你应该在 bootstrap/app.php 文件中 $app 变量返回之前调用此方法:

php
$app->configureMonologUsing(function ($monolog) {
    $monolog->pushHandler(...);
});

return $app;

自定义频道名称

默认情况下,Monolog 实例化时的名称与当前环境匹配,例如 productionlocal。要更改此值,请在 app.php 配置文件中添加 log_channel 选项:

php
'log_channel' => env('APP_LOG_CHANNEL', 'my-app-name'),

异常处理器

报告方法

所有异常都由 App\Exceptions\Handler 类处理。此类包含两个方法:reportrender。我们将详细检查这两个方法。report 方法用于记录异常或将其发送到外部服务,如 BugsnagSentry。默认情况下,report 方法将异常传递给基类,在那里记录异常。然而,你可以随意记录异常。

例如,如果你需要以不同方式报告不同类型的异常,可以使用 PHP 的 instanceof 比较运算符:

php
/**
 * 报告或记录异常。
 *
 * 这是一个将异常发送到 Sentry、Bugsnag 等的好地方。
 *
 * @param  \Exception  $exception
 * @return void
 */
public function report(Exception $exception)
{
    if ($exception instanceof CustomException) {
        //
    }

    return parent::report($exception);
}

report 辅助函数

有时你可能需要报告异常但继续处理当前请求。report 辅助函数允许你使用异常处理器的 report 方法快速报告异常而不渲染错误页面:

php
public function isValid($value)
{
    try {
        // 验证值...
    } catch (Exception $e) {
        report($e);

        return false;
    }
}

按类型忽略异常

异常处理器的 $dontReport 属性包含一个不记录的异常类型数组。例如,由 404 错误以及其他几种类型的错误导致的异常不会写入日志文件。你可以根据需要将其他异常类型添加到此数组中:

php
/**
 * 不应报告的异常类型列表。
 *
 * @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,
];

渲染方法

render 方法负责将给定异常转换为应发送回浏览器的 HTTP 响应。默认情况下,异常被传递给基类,基类为你生成响应。然而,你可以自由检查异常类型或返回自己的自定义响应:

php
/**
 * 将异常渲染为 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);
}

可报告与可渲染异常

你可以在自定义异常上直接定义 reportrender 方法,而不是在异常处理器的 reportrender 方法中进行类型检查。当这些方法存在时,框架将自动调用它们:

php
<?php

namespace App\Exceptions;

use Exception;

class RenderException extends Exception
{
    /**
     * 报告异常。
     *
     * @return void
     */
    public function report()
    {
        //
    }

    /**
     * 将异常渲染为 HTTP 响应。
     *
     * @param  \Illuminate\Http\Request
     * @return \Illuminate\Http\Response
     */
    public function render($request)
    {
        return response(...);
    }
}

HTTP 异常

某些异常描述来自服务器的 HTTP 错误代码。例如,这可能是一个“页面未找到”错误(404)、一个“未授权错误”(401)或甚至是开发人员生成的 500 错误。为了从应用程序的任何地方生成这样的响应,你可以使用 abort 辅助函数:

php
abort(404);

abort 辅助函数将立即引发一个异常,该异常将由异常处理器渲染。可选地,你可以提供响应文本:

php
abort(403, 'Unauthorized action.');

自定义 HTTP 错误页面

Laravel 使得为各种 HTTP 状态代码显示自定义错误页面变得容易。例如,如果你希望自定义 404 HTTP 状态代码的错误页面,请创建一个 resources/views/errors/404.blade.php。此文件将在应用程序生成的所有 404 错误时提供。此目录中的视图应命名为与其对应的 HTTP 状态代码相匹配。abort 函数引发的 HttpException 实例将作为 $exception 变量传递给视图:

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

日志记录

Laravel 在强大的 Monolog 库之上提供了一个简单的抽象层。默认情况下,Laravel 被配置为在 storage/logs 目录中为你的应用程序创建一个日志文件。你可以使用 Log facade 将信息写入日志:

php
<?php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * 显示给定用户的个人资料。
     *
     * @param  int  $id
     * @return Response
     */
    public function showProfile($id)
    {
        Log::info('显示用户的个人资料:'.$id);

        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}

日志记录器提供了 RFC 5424 中定义的八个日志级别:emergencyalertcriticalerrorwarningnoticeinfodebug

php
Log::emergency($message);
Log::alert($message);
Log::critical($message);
Log::error($message);
Log::warning($message);
Log::notice($message);
Log::info($message);
Log::debug($message);

上下文信息

一个上下文数据数组也可以传递给日志方法。此上下文数据将与日志消息一起格式化并显示:

php
Log::info('用户登录失败。', ['id' => $user->id]);

访问底层 Monolog 实例

Monolog 有多种额外的处理器可用于日志记录。如果需要,你可以访问 Laravel 使用的底层 Monolog 实例:

php
$monolog = Log::getMonolog();