Laravel 5.5 异常处理 & 错误日志的解决


Posted in PHP onOctober 17, 2019

简介

Laravel 默认已经为我们配置好了错误和异常处理,我们在 App\Exceptions\Handler 类中触发异常并将响应返回给用户。

此外,Laravel 还集成了 Monolog 日志库以便提供各种功能强大的日志处理器,默认情况下,Laravel 已经为我们配置了一些处理器,我们可以选择单个日志文件,也可以选择记录错误信息到系统日志。

配置

调试模式

配置文件 config/app.php 中的 debug 配置项表示是否开启调试模式,调试模式下会将错误信息直接暴露给客户端。

默认情况下,该配置项通过 .env 文件中的环境变量 APP_DEBUG 进行设置,默认值为 true ,即开启调试模式。

对本地开发而言,你应该设置环境变量 APP_DEBUG 值为 true。在生产环境,该值应该被设置为 false。如果在生产环境被设置为 true,就有可能将一些敏感的信息暴露给终端用户。

日志存储

Laravel 支持的日志文件类型为 single, daily, syslog 和 errorlog。

single: 所有的日志信息会记录到单个日志文件里。

daily:按天生成日志文件。

syslog: 通过系统 syslog 服务处理日志信息。

errorlog: 通过 PHP error_log 处理器处理日志信息。

如果你想要日志文件按天生成而不是生成并记录到单个文件,应该在配置文件 config/app.php 中设置 log 值如下:

'log' => 'daily'

注:底层处理机制可以参考 Illuminate\Log\LogServiceProvider 中的实现逻辑。

日志文件最大生命周期

使用 daily 日志模式的时候,Laravel 默认最多为我们保留最近 5 天的日志,如果你想要修改这个时间,需要添加一个配置 log_max_files 到 app 配置文件:

'log_max_files' => 30

日志错误级别

使用 Monolog 的时候,日志消息可能有不同的错误级别,默认情况下,Laravel 将所有级别日志写到存储器,但是在生产环境中,你可能想要配置最低错误级别,这可以通过在配置文件 app.php 中添加配置项 log_level 来实现。

该配置项被配置后,Laravel 会记录所有错误级别大于等于这个指定级别的日志。

例如,如果配置 log_level 为 error ,则会记录 error、critical、alert 以及 emergency 级别的日志信息。

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

注:Monolog 支持以下错误级别:debug、info、notice、warning、error、critical、alert、emergency。

自定义 Monolog 配置

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

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

自定义频道名称

默认情况下,Monolog 会通过一个与当前环境匹配的名字进行实例化,例如 production 或 local。如果想修改这个值,需要添加 log_channel 配置项到配置文件 config/app.php:

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

异常处理器

所有异常都由类 App\Exceptions\Handler 处理,该类包含两个方法:report 和 render。

report 方法

report 方法用于记录异常并将其发送给外部服务如 Bugsnag 或 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) {
    //
  }
  parent::report($exception);
}

report 辅助函数

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

public function isValid($value)
{
  try {
    // Validate the value...
  } catch (Exception $e) {
    report($e);
 
    return false;
  }
}

通过类型忽略异常

异常处理器的 $dontReport 属性包含一个不会被记录的异常类型数组,默认情况下,404 错误异常不会被写到日志文件,如果需要的话你可以添加其他异常类型到这个数组:

/**
 * 不应该被报告的异常类型列表.
 *
 * @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 响应。

默认情况下,异常被传递给为你生成响应的基类。当然,你也可以按照自己的需要检查异常类型或者返回自定义响应:

/**
 * 将异常渲染到HTTP响应中
 *
 * @param \Illuminate\Http\Request $request
 * @param \Exception $e
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $e){
  if ($e instanceof CustomException) {
    return response()->view('errors.custom', [], 500);
  }
 
  return parent::render($request, $e);
}

可报告 & 可渲染异常

除了在异常处理器的 report 和 render 方法中进行异常类型检查外,还可以在自定义异常中直接定义 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 异常

有些异常描述来自服务器的 HTTP 错误码,例如,这可能是一个“页面未找到”错误(404),“认证失败错误”(401)亦或是程序出错造成的500错误,为了在应用中生成这样的响应,可以使用 abort 辅助函数:

abort(404);

abort 辅助函数会立即引发一个会被异常处理器渲染的异常,此外,你还可以像这样提供响应描述:

abort(403, '未授权操作');

该方法可在请求生命周期的任何时间点使用。

自定义 HTTP 错误页面

在 Laravel 中,返回不同 HTTP 状态码的错误页面很简单,例如,如果你想要自定义 404 错误页面,创建一个 resources/views/errors/404.blade.php 文件,该视图文件用于渲染程序返回的所有 404 错误。

需要注意的是,该目录下的视图命名应该和相应的 HTTP 状态码相匹配。abort 函数触发的 HttpException 异常会以 $exception 变量的方式传递给视图:

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

日志

Laravel 基于强大的 Monolog 库提供了简单的日志抽象层,默认情况下,Laravel 的日志配置是为应用记录单个日志文件。

日志文件的存储位置是 storage/logs 目录。

/*
|--------------------------------------------------------------------------
| Logging Configuration
|--------------------------------------------------------------------------
|
| Here you may configure the log settings 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 Settings: "single", "daily", "syslog", "errorlog"
|
*/
 
'log' => env('APP_LOG', 'single'),
 
'log_level' => env('APP_LOG_LEVEL', 'debug'),

应用运行过程中,所有级别大于或等于 debug 的错误日志都会被自动记录到 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
{
  /**
   * 显示指定用户的属性
   *
   * @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)]);
  }
}

该日志记录器提供了 RFC 5424 中定义的八种日志级别:emergency、alert、critical、error、warning、notice、info 和 debug。

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

上下文信息

上下文数据也会以数组形式传递给日志方法,然后和日志消息一起被格式化和显示:

Log::info('User failed to login.', ['id' => $user->id]);

访问底层 Monolog 实例

Monolog 有多个可用于日志的处理器,如果需要的话,你可以访问 Laravel 使用的底层 Monolog 实例:

$monolog = Log::getMonolog();

以上这篇Laravel 5.5 异常处理 & 错误日志的解决就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
超级简单的发送邮件程序
Oct 09 PHP
php下几个常用的去空、分组、调试数组函数
Feb 22 PHP
php获取当前网址url并替换参数或网址的方法
Jun 06 PHP
php生成随机密码的几种方法
Jan 17 PHP
php提示undefined index的几种解决方法
May 21 PHP
php在window iis的莫名问题的测试方法
May 14 PHP
php5.3 注意事项说明
Jul 01 PHP
php把数据表导出为Excel表的最简单、最快的方法(不用插件)
May 10 PHP
PHP实现长文章分页实例代码(附源码)
Feb 03 PHP
thinkphp,onethink和thinkox中验证码不显示的解决方法分析
Jun 06 PHP
PHP实现的常规正则验证helper公共类完整实例
Apr 27 PHP
如何用PHP实现多线程编程
May 26 PHP
PHP封装请求类实例分析【基于Yii框架】
Oct 17 #PHP
使用laravel指定日志文件记录任意日志
Oct 17 #PHP
Laravel 修改默认日志文件名称和位置的例子
Oct 17 #PHP
thinkPHP事务操作简单案例分析
Oct 17 #PHP
使用laravel根据用户类型来显示或隐藏字段
Oct 17 #PHP
laravel model模型定义实现开启自动管理时间created_at,updated_at
Oct 17 #PHP
TP5框架请求响应参数实例分析
Oct 17 #PHP
You might like
php缓冲 output_buffering的使用详解
2013/06/13 PHP
php编写简单的文章发布程序
2015/06/18 PHP
PHP Ajax跨域问题解决方案代码实例
2020/08/01 PHP
javascript引导程序
2008/10/26 Javascript
Javascript学习笔记9 prototype封装继承
2010/01/11 Javascript
JS 面向对象之神奇的prototype
2011/02/26 Javascript
jQuery 1.5.1 发布,全面支持IE9 修复大量bug
2011/02/26 Javascript
输入密码检测大写是否锁定js实现代码
2012/12/03 Javascript
为Javascript中的String对象添加去除左右空格的方法(示例代码)
2013/11/30 Javascript
使用jQuery动态加载js脚本文件的方法
2014/04/03 Javascript
JavaScript实现班级随机点名小应用需求的具体分析
2014/05/12 Javascript
解决jquery实现的radio重新选中的问题
2015/07/03 Javascript
JavaScript中数组继承的简单示例
2015/07/29 Javascript
javascript实现瀑布流加载图片原理
2016/02/02 Javascript
javascript 常用验证函数总结
2016/06/28 Javascript
js实现StringBuffer的简单实例
2016/09/02 Javascript
js对象浅拷贝和深拷贝详解
2016/09/05 Javascript
bootstrap实现每隔5秒自动轮播效果
2016/12/20 Javascript
js addDqmForPP给标签内属性值加上双引号的函数
2016/12/24 Javascript
vue.js事件处理器是什么
2017/03/20 Javascript
iOS + node.js使用Socket.IO框架进行实时通信示例
2017/04/14 Javascript
JavaScript惰性载入函数实例分析
2019/03/27 Javascript
基于JS实现前端压缩上传图片的实例代码
2019/05/14 Javascript
Python获取SQLite查询结果表列名的方法
2017/06/21 Python
Python二维数组实现求出3*3矩阵对角线元素的和示例
2019/11/29 Python
python3实现从kafka获取数据,并解析为json格式,写入到mysql中
2019/12/23 Python
Python实现将元组中的元素作为参数传入函数的操作
2020/06/05 Python
H5离线存储Manifest原理及使用
2020/04/28 HTML / CSS
英国在线自行车店:Merlin Cycles
2018/08/20 全球购物
我的网上商城创业计划书
2013/12/26 职场文书
关于爱情的广播稿
2014/01/16 职场文书
培训主管岗位职责
2014/02/01 职场文书
学生顶撞老师的检讨书
2014/09/17 职场文书
降价通知函
2015/04/23 职场文书
离婚协议书范文2016
2016/03/18 职场文书
优秀的商业计划书,让融资一步到位
2019/05/07 职场文书