laravel 中自定义异常

2019-03-15  本文已影响0人  JJNile

前言

项目上线时,我们不能将系统的报错信息反馈给用户,因为这样特别不安全和友好,所以我们要设置.env中APP_DEBUG = false。

尽管这样不会在显示代码错误的信息,但是laravel会将显示空白的 Whoops, looks like something went wrong,这无法给访问者提供任何有价值的信息也不美观。

所以我们需要需要捕捉错误,处理它们,然后用实际可以理解的错误信息返回给用户。

源码解析

首先看下laravel中的异常处理类:

app/Exceptions/Handler.php

 <?php

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

class Handler extends ExceptionHandler
{
    // 不被处理的异常错误
    protected $dontReport = [
        InvalidRequestException::class,
    ];

    // 认证异常时不被flashed的数据
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    // 上报异常至错误driver,如日志文件(storage/logs/laravel.log),第三方日志存储分析平台
    public function report(Exception $exception)
    {
        parent::report($exception);
    }

    // 将异常信息响应给客户端
    public function render($request, Exception $exception)
    {
        return parent::render($request, $exception);
    }
}

当 Laravel 处理一次请求时,在启动文件中注册了以下服务:

bootstrap/app.php

.
.
// 绑定 http 服务提供者
$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);
// 绑定 cli 服务提供者
$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Console\Kernel::class
);
// 这里将异常处理器的服务提供者绑定到了 `App\Exceptions\Handler::class`
$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);
.
.

我们大概了解了异常,其中最主要的两个方法是:

report() 如果你想要做一些额外的日志记录,则使用report(), 比如将错误发送到电子邮件,Slack等。

render() 如果你想直接从Exception类重定向错误或返回HTTP响应(如自己的 Blade 文件),则使用render()

那么现在在自定义常用的两个异常类:用户错误行为触发的异常和系统内部异常

自定义异常

自定义常用的两个异常:

  1. 用户错误行为触发的异常
  2. 系统内部异常

用户错误行为触发的异常

$ php artisan make:exception InvalidRequestException

app/Exceptions/InvalidRequestException.php

<?php
namespace App\Exceptions;

use Exception;
use Illuminate\Http\Request;
use Throwable;

class InvalidRequestException extends Exception {
    public function __construct(string $message = "", int $code = 0, Throwable $previous = null) {
        parent::__construct($message, $code, $previous);
    }

    public function render(Request $request) {

        // 如果是 AJAX 请求则返回 JSON 格式的数据
        if ($request->expectsJson()) {
            return response()->json(['msg' => $this->message], $this->code);
        }

        return view('error', ['msg' => $this->message]);
    }
}


系统内部异常

$ php artisan make:exception InternalException

app/Exceptions/InternalException.php

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Http\Request;
use Throwable;

class InternalException extends Exception {
    protected $msgForUser;

    public function __construct(string $message = "", string $msgForUser = "系统内部错误", int $code = 0, Throwable $previous = null) {
        parent::__construct($message, $code, $previous);
        $this->msgForUser = $msgForUser;
    }

    public function render(Request $request) {

        if ($request->expectsJson()) {
            return response()->json(['msg' => $this->msgForUser], $this->code);
        }

        return view('error', ['msg' => $this->msgForUser]);
    }


}

应用到代码中

抛出异常

use App\Exceptions\InvalidRequestException;
.
.
.
if (!$activate) {
    throw new InvalidRequestException('不再进行中');
}

参考

https://segmentfault.com/a/1190000018381889
https://juejin.im/entry/5af517c26fb9a07acd4dc5b8
https://swoole.app/2018/04/11/laravel%E4%BD%BF%E7%94%A8%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BC%82%E5%B8%B8%E7%B1%BB/

上一篇 下一篇

猜你喜欢

热点阅读