欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Laravel異常上下文解決方案分享

 更新時間:2022年01月06日 16:14:46   作者:overtrue  
異常處理是編程中十分重要但也最容易被人忽視的語言特性,下面這篇文章主要給大家介紹了關(guān)于Laravel異常上下文解決方案的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下

前言

異常時我們通常希望在用戶側(cè)給一個友好的提示,但默認使用框架的異常處理方案是不 OK 的。

最近項目遇到一個情況,我們在遇到用戶訪問某個信息沒有權(quán)限的時候,希望提示詳細的原因,比如當訪問一個團隊資源時非成員訪問的場景下會提示一個:您不是 [xxxxxx] 團隊的成員,暫時無法查看,可<申請加入>,同時需要顯示打碼后的團隊名稱,以及加入按鈕,可是接口方的邏輯是當沒有權(quán)限時直接 abort 了:

abort_if(!$user->isMember($resouce->team), 403, '您無權(quán)訪問該資源');

得到的響應(yīng)結(jié)果如下:

HTTP/1.0 403 Forbidden

{
	"message": "您無權(quán)訪問該資源"
}

我們不可能將 message 用 html 來完成前端提示頁的展示,這樣耦合性太強,違背了前后端分離的原則。我們的目標是返回如下的格式即可解決:

HTTP/1.0 403 Forbidden

{
	"message": "您無權(quán)訪問該資源",
	"team": {
		"id": "abxT8sioa0Ms",
		"name": "CoDesign****"
	}
}

通過攜帶上下文的方法傳遞數(shù)據(jù),方便了前端同學自由組合。

開始改造

當然這并不是什么復雜的事情,直接修改原來的 abort_if 即可解決:

- abort_if(!$user->isMember($resouce->team), 403, '您無權(quán)訪問該資源');
+ if (!$user->isMember($resouce->team)) {
+	return response()->json([
+		'message' => '您無權(quán)訪問該資源',
+		'team' => [
+			'id' => $resouce->team_id,
+			'name'=> $resouce->team->desensitised_name,
+		]
+	], 403);
+ }

這樣看起來解決了問題,可是試想一下,如果是在閉包里面檢測到異常想要退出,上面這種 return 式的寫法就會比較難搞了,畢竟 return 只會終止最近的上下文環(huán)境,我們還是希望像 abort 一樣能終止整個應(yīng)用的執(zhí)行,再進行另一番改造。

優(yōu)化實現(xiàn)

看了 abort 源碼,我發(fā)現(xiàn)它的第一個參數(shù)其實支持 \Symfony\Component\HttpFoundation\Response 實例,而上面??我們 return 的結(jié)果就是它的實例,所以我們只需要改成這樣就可以了:

 if (!$user->isMember($resouce->team)) {
	abort(response()->json([
		'message' => '您無權(quán)訪問該資源',
		'team' => [
			'id' => $resouce->team_id,
			'name'=> $resouce->team->desensitised_name,
		]
	], 403));
 }

新的問題來了,如果需要復用的時候還是比較尷尬,這段代碼將會重復出現(xiàn)在各種有此權(quán)限判斷的地方,這并不是我們想要的。

邏輯復用

為了達到邏輯復用,我認證看了 \App\Exceptions\Handler 的實現(xiàn),發(fā)現(xiàn)父類的 render 方法還有這么一個設(shè)計:

public function render($request, Throwable $e)
{
    if (method_exists($e, 'render') && $response = $e->render($request)) {
        return Router::toResponse($request, $response);
    } elseif ($e instanceof Responsable) {
        return $e->toResponse($request);
    }

    //...

所以,我們可以將這個邏輯抽離為一個獨立的異常類,實現(xiàn) render 方法即可:

$ ./artisan make:exception NotTeamMemberException

代碼如下:

<?php

namespace App\Exceptions;

use App\Team;

class NotTeamMemberException extends \Exception
{
    public Team $team;

    public function __construct(Team $team, $message = "")
    {
        $this->team = $team;
        parent::__construct($message, 403);
    }

    public function render()
    {
        return response()->json(
            [
                'message' => !empty($this->message) ? $this->message : '您無權(quán)訪問該資源',
                'team' => [
                    'id' => $this->team->id,
                    'name' => $this->team->desensitised_name,
                ],
            ],
            403
        );
    }
}

這樣一來,我們的邏輯就變成了:

if (!$user->isMember($resouce->team)) {
 	throw new NotTeamMemberException($resouce->team, '您無權(quán)訪問該資源');
}

當然也可以簡化為:

\throw_if(!$user->isMember($resouce->team), NotTeamMemberException::class, $resouce->team, '您無權(quán)訪問該資源');

問題到這里總算以一個比較完美的方式解決了,如果你有更好的方案歡迎評論探討。

總結(jié)

到此這篇關(guān)于Laravel異常上下文解決方案的文章就介紹到這了,更多相關(guān)Laravel異常上下文解決內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論