前言
项目上线时,我们不能将系统的报错信息反馈给用户,因为这样特别不安全和友好,所以我们要设置.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()
那么现在在自定义常用的两个异常类:用户错误行为触发的异常和系统内部异常
自定义异常
自定义常用的两个异常:
- 用户错误行为触发的异常
- 系统内部异常
用户错误行为触发的异常
$ 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/
网友评论