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 相关文章推荐
一个php作的文本留言本的例子(二)
Oct 09 PHP
Ajax+PHP 边学边练 之二 实例
Nov 24 PHP
解析php时间戳与日期的转换
Jun 06 PHP
2个Codeigniter文件批量上传控制器写法例子
Jul 25 PHP
windows8.1下Apache+Php+MySQL配置步骤
Oct 30 PHP
php时间函数用法分析
May 28 PHP
PHP二维数组去重算法
Dec 17 PHP
在IIS下安装PHP扩展的方法(超简单)
Apr 10 PHP
PHP实现自动发送邮件功能代码(qq 邮箱)
Aug 18 PHP
基于ThinkPHP5.0实现图片上传插件
Sep 25 PHP
PHP面向对象程序设计(OOP)之方法重写(override)操作示例
Dec 21 PHP
PHP终止脚本运行三种实现方法详解
Sep 01 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验证码函数的使用示例
2013/05/03 PHP
用php实现选择排序的解决方法
2013/05/04 PHP
JS网络游戏-(模拟城市webgame)提供的一些例子下载
2007/10/14 Javascript
JavaScript实现拼音排序的方法
2012/11/20 Javascript
AngularJS基础学习笔记之控制器
2015/05/10 Javascript
JS中处理时间之setUTCMinutes()方法的使用
2015/06/12 Javascript
JS根据key值获取URL中的参数值及把URL的参数转换成json对象
2015/08/26 Javascript
js密码强度校验
2015/11/10 Javascript
JavaScript解八皇后问题的方法总结
2016/06/12 Javascript
JavaScript中的冒泡排序法
2016/08/03 Javascript
JS控制div跳转到指定的位置的几种解决方案总结
2016/11/05 Javascript
BootStrap3使用错误记录及解决办法
2016/12/22 Javascript
Angular2使用Guard和Resolve进行验证和权限控制
2017/04/24 Javascript
[50:29]2014 DOTA2华西杯精英邀请赛 5 24 DK VS iG
2014/05/26 DOTA
python学习之面向对象【入门初级篇】
2017/01/21 Python
PyQt5+requests实现车票查询工具
2019/01/21 Python
python如何获取当前文件夹下所有文件名详解
2019/01/25 Python
使用keras根据层名称来初始化网络
2020/05/21 Python
CSS3 绘制BMW logo实的现代码
2013/04/25 HTML / CSS
html5贪吃蛇游戏使用63行代码完美实现
2013/06/25 HTML / CSS
在校生党员自我评价
2013/09/25 职场文书
医学生自我鉴定范文
2013/11/08 职场文书
岗位职责的定义
2013/11/10 职场文书
天鹅的故事教学反思
2014/02/04 职场文书
少先队学雷锋活动总结范文
2014/03/09 职场文书
乡镇四风对照检查材料
2014/08/31 职场文书
市场营销计划书范文
2015/01/16 职场文书
情人节活动总结范文
2015/02/05 职场文书
关于法制教育的宣传语
2015/07/13 职场文书
大学生暑假实习总结
2015/07/13 职场文书
团支部组织委员竞选稿
2015/11/21 职场文书
高中美术教学反思
2016/02/17 职场文书
创业计划书之牛肉汤快餐店
2019/10/08 职场文书
如何解决.cuda()加载用时很长的问题
2021/05/24 Python
浅析CSS在DevTools 中架构演变
2021/10/05 HTML / CSS
HTML中实现音乐或视频自动播放案例详解
2022/05/30 HTML / CSS