前言
項目上線時呕童,我們不能將系統(tǒng)的報錯信息反饋給用戶愧驱,因為這樣特別不安全和友好耗拓,所以我們要設置.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的數(shù)據(jù)
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(), 比如將錯誤發(fā)送到電子郵件懂傀,Slack等趾诗。
render() 如果你想直接從Exception類重定向錯誤或返回HTTP響應(如自己的 Blade 文件),則使用render()
那么現(xiàn)在在自定義常用的兩個異常類:用戶錯誤行為觸發(fā)的異常和系統(tǒng)內(nèi)部異常
自定義異常
自定義常用的兩個異常:
- 用戶錯誤行為觸發(fā)的異常
- 系統(tǒng)內(nèi)部異常
用戶錯誤行為觸發(fā)的異常
$ 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 格式的數(shù)據(jù)
if ($request->expectsJson()) {
return response()->json(['msg' => $this->message], $this->code);
}
return view('error', ['msg' => $this->message]);
}
}
系統(tǒng)內(nèi)部異常
$ 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 = "系統(tǒng)內(nèi)部錯誤", 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/