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 相关文章推荐
浅谈Windows下 PHP4.0与oracle 8的连接设置
Oct 09 PHP
不错的一篇面向对象的PHP开发模式(简写版)
Mar 15 PHP
php cli 方式 在crotab中运行解决
Feb 08 PHP
php抽奖小程序的实现代码
Jun 18 PHP
php中如何防止表单的重复提交
Aug 02 PHP
php获取客户端电脑屏幕参数的方法
Jan 09 PHP
PHP、Python和Javascript的装饰器模式对比
Feb 03 PHP
WordPress中制作导航菜单的PHP核心方法讲解
Dec 11 PHP
分析php://output和php://stdout的区别
May 06 PHP
PHP设计模式之观察者模式定义与用法示例
Aug 04 PHP
thinkPHP5.0框架验证码调用及点击图片刷新简单实现方法
Sep 07 PHP
Yii2.0框架模型多表关联查询示例
Jul 18 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
PHP7 新特性详细介绍
2016/09/06 PHP
PHP如何搭建百度Ueditor富文本编辑器
2018/09/21 PHP
PHP实现会员账号单唯一登录的方法分析
2019/03/07 PHP
TP5框架实现签到功能的方法分析
2020/04/05 PHP
客户端 使用XML DOM加载json数据的方法
2010/09/28 Javascript
javascript中处理时间戳为日期格式的方法
2014/01/02 Javascript
简单js代码实现selece二级联动(推荐)
2014/02/18 Javascript
JavaScript基本的输出和嵌入式写法教程
2015/10/20 Javascript
JavaScript几种数组去掉重复值的方法推荐
2016/04/12 Javascript
微信公众号支付H5调用支付解析
2016/11/04 Javascript
JS控制div跳转到指定的位置的几种解决方案总结
2016/11/05 Javascript
浅谈js中几种实用的跨域方法原理详解
2016/12/02 Javascript
JS实现滑动门效果的方法详解
2016/12/19 Javascript
JS判断一个数是否是水仙花数
2017/06/11 Javascript
微信小程序canvas写字板效果及实例
2017/06/15 Javascript
Vue 简单实现前端权限控制的示例
2020/12/25 Vue.js
Python实现截屏的函数
2015/07/26 Python
Python 类与元类的深度挖掘 I【经验】
2016/05/06 Python
利用Python自动监控网站并发送邮件告警的方法
2016/08/24 Python
Python编程argparse入门浅析
2018/02/07 Python
python按综合、销量排序抓取100页的淘宝商品列表信息
2018/02/24 Python
对Xpath 获取子标签下所有文本的方法详解
2019/01/02 Python
Django框架静态文件使用/中间件/禁用ip功能实例详解
2019/07/22 Python
利用python计算时间差(返回天数)
2019/09/07 Python
python银行系统实现源码
2019/10/25 Python
python如何进入交互模式
2020/07/06 Python
canvas画布实现手写签名效果的示例代码
2019/04/23 HTML / CSS
意大利大型购物中心:Oliviero.it
2017/10/19 全球购物
资生堂英国官网:Shiseido英国
2020/12/30 全球购物
Bandier官网:奢侈、时尚前卫的健身服装首选目的地
2020/07/05 全球购物
生产车间实习自我鉴定
2013/09/23 职场文书
外语系毕业生自荐信范文
2013/12/16 职场文书
关爱残疾人标语
2014/06/25 职场文书
2015年基层党建工作汇报材料
2015/06/25 职场文书
2015年公路路政个人工作总结
2015/07/24 职场文书
2016年寒假见闻
2015/10/10 职场文书