Laravel 文档阅读:错误 & 日志记录
简介
Laravel 项目里已经为你配置好了错误和异常处理。项目中的异常都是在 App\Exceptions\Handler
类中处理并渲染给用户的。接下来,我们将深入到该类中进行讲解。
Laravel 是利用了 Monolog 这个库记录日志的,这个库里包含了大量的日志处理方法。Laravel 为你配置了这些处理方法,提供了单个日志文件、每日一个日志文件和将错误信息写入系统日志这几个选项供你选择。
配置
错误内容
config/app.php
配置文件中的 debug
选项决定错误发生时,显示给用户看的内容是多啊还是少,是详细啊还是简略。默认,这个选项值优先使用 .env
文件里 APP_DEBUG
字段的设定值。
对于本地开发环境,把 APP_DEBUG
设定为 true
,而在生产环境,应该总是设置为 false
。如果在生产环境开启了 Debug 模式,项目中的一些敏感信息就会暴露给终端用户的,后果可能不堪设想。
日志存储
Laravel 开箱支持以下几种日志记录设定:single
、daily
、syslog
和 errorlog
。修改 config/app.php
配置文件中的 log
选项即可使用你想要的日志存储模式。例如,我们不希望日志都记录在一个文件里,而是一天的日志单独放在一个文件里,那么把 log
设定为 daily
即可:
'log' => 'daily'
设定日志文件的最大数量
使用 daily
日志模式时,默认 Laravel 只会保存最近 5 日的日志文件。如果要调整,要在 config/app.php
再添加个 log_max_files
字段指定即可:
'log_max_files' => 30
日志安全级别
Laravel 日志管理使用的是 Monolog 这个 PHP 日志库,Laravel 的 日志安全级别就是指 Monolog 所能支持的日志安全级别。由 config/app.php
的 log_level
字段值决定,默认是 debug
。
Monolog 日志安全级别从低到高分别是:debug
、info
、notice
、warning
、error
、critical
、alert
和 emergency
。
安全级别设定好后,Laravel 会记录包括当前级别在内、所有更高级别的日志类型。就是说,当你设定 log_level
的值为 error
的时候,被记录的消息范围包括:error
、critical
、alert
和 emergency
。
'log_level' => env('APP_LOG_LEVEL', 'error'),
自定义 Monolog 配置
如果你想完全掌控 Monolog 在 Laravel 中的配置,可以使用 $app
的 configureMonologUsing
方法,这个方法是在 bootstrap/app.php
中返回 $app
之前调用。
$app->configureMonologUsing(function ($monolog) {
$monolog->pushHandler(...);
});
return $app;
自定义频道名
默认,Monolog 初始化采用的名称与当前环境一致,比如 production
或者 local
。如果需要自定义,要在 config/app.php
添加一个 log_channel
选项。
'log_channel' => env('APP_LOG_CHANNEL', 'my-app-name'),
异常处理程序
report
方法
所有异常都是由 App\Exceptions\Handler
类处理的,这个类中包含两个方法:report
和 render
,我们将分别介绍。report
方法用来记录异常,或者将异常日志发送给像 Bugsnnag、Sentry 这样的第三方服务。默认,report
方法会简单地把异常直接传递给基类,让基类处理记录日志的操作。当然,记录日志的方式你也可以自在设定。
例如,我们使用 PHP instanceof
比较操作符,根据异常实例的类型记录异常。
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* @param \Exception $exception
* @return void
*/
public function report(Exception $exception)
{
if ($exception instanceof CustomException) {
//
}
return parent::report($exception);
}
report
辅助函数
有时,需要在报告异常的同时接着出来当前的请求,全局 report
辅助函数就是做这个的,它在报告异常的时候,不会产生异常页面。
public function isValid($value)
{
try {
// Validate the value...
} catch (Exception $e) {
report($e);
return false;
}
}
忽略的异常类型
异常处理器中的 dontReport
数组属性,用来设定不被处理的异常类型。例如,例如,404 错误导致的异常以及其他几个类型的错误不会写入日志文件。
/**
* A list of the exception types that should not be reported.
*
* @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
方法
render
方法负责将一个异常转换为发送给浏览器的 HTTP 响应。默认传递给基类的异常都会被处理成一个响应,你或者可以根据异常类型类自定义异常响应界面。
/**
* Render an exception into an HTTP response.
*
* @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
方法的异常类
如果异常类中包含了 report
和 render
,这就避免了我们在 Handler
类中检查异常类型,然后 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 异常
你可以使用全局辅助函数 abort
直接在程序里抛出异常,比如「页面未找到」的 404 错误,「未认证」 的 401 错误,甚至是 500 「程序内部错误」。
abort(404);
abort
抛出的异常会立即被 Handler
处理,渲染成错误页面。你也可以使用第二个可选参数,设置响应文本。
abort(403, 'Unauthorized action.');
自定义 HTTP 错误页面
根据 HTTP 状态码来显示对应的错误页面,在 Laravel 中操作起来非常简单。比如,你要为 404 HTTP 状态码指定一个错误页面,创建 resources/views/errors/404.blade.php
文件即可,当 404 异常发生时,会自动采用这个页面。就是说你在 resources/views/errors/
目录下,直接以 HTTP 状态码定义的文件,最终都会在对应异常发生时采用、并渲染出来。abort
函数产生的 HttpException
实例对象会以 $exception
变量的形式传递给视图。
<h2>{{ $exception->getMessage() }}</h2>
日志记录
Laravel 在强大的 Monolog 库之上提供了一个简单的抽象层。默认,Laravel 是在 storage/logs
目录下创建日志文件的。你可以使用 Log 门面记录日志。
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Show the profile for the given user.
*
* @param int $id
* @return Response
*/
public function showProfile($id)
{
Log::info('Showing user profile for user: '.$id);
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
咱们的 Log 提供了在 RFC 5424 定义的 8 个日志等级,分别是: emergency、alert、critical、error、warning、notice、info 和 debug。
Log::emergency($message);
Log::alert($message);
Log::critical($message);
Log::error($message);
Log::warning($message);
Log::notice($message);
Log::info($message);
Log::debug($message);
文本信息
也可以给 Log 的这些方法传递可选的文本信息,这些信息会被格式化,输出在日志信息中。
Log::info('User failed to login.', ['id' => $user->id]);
获得底层 Monolog 实例对象
Monolog 还有许多其他的日志处理方法,如果需要,你可以直接访问底层的 Monolog 实例对象:
$monolog = Log::getMonolog();
本作品采用《CC 协议》,转载必须注明作者和本文链接