日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

api laravel 统一返回方法_Laravel API 错误处理:当异常时,如何返回消息

發布時間:2024/7/19 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 api laravel 统一返回方法_Laravel API 错误处理:当异常时,如何返回消息 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

image

基于 API 的項目開發越來越受歡迎,并且使用 Laravel 就能很容易實現。但是在針對如何處理各種異常的話題很少被提及。所以 API 的使用者們經常會抱怨除了收到 Server error ,很少有更多的錯誤信息。那么,我們該如何優雅的處理 API 錯誤讓其變得更具有可讀性呢?

目標:狀態碼 + 錯誤消息

對于 API 開發來講,正確的錯誤描述甚至比僅基于 Web 瀏覽器的項目更為重要。作為使用者,我們也可以通過瀏覽器消息提示清楚地了解錯誤以及該怎么解決。但對于 API 本身來說,它們是由軟件而非人員使用的,因此返回的結果應 readable by machines 。這意味著HTTP狀態代碼就必不可少。

API 給每個請求都會返回一個狀態碼,請求成功通常是 200,或者是以 2 開頭的其他狀態碼。

如果返回錯誤響應,則該響應不應包含2xx代碼,以下是最常見的錯誤代碼:

| 狀態碼 | 描述 |

| 404 | 未找到(請求資源不存在) |

| 401 | 未認證 (需要登錄) |

| 403 | 沒有權限 |

| 400 | 錯誤的請求(URL或參數不正確) |

| 422 | 驗證失敗 |

| 500 | 服務器錯誤 |

注意:返回響應時,如果沒有添加狀態碼,Laravel 會自動指定狀態碼,但并不能保證所指定的狀態碼正確。所以最好還是自己手動添加正確的狀態碼。

除此之外,我們還要考慮到 human-readable messages。因此,典型的響應應包含 HTTP 錯誤代碼和 JSON 結果,如下所示:

{

"error": "Resource not found"

}

理想情況下,它應該包含更多詳細信息,以幫助API使用者處理錯誤。這是Facebook API如何返回錯誤的示例:

{

"error": {

"message": "Error validating access token: Session has expired on Wednesday, 14-Feb-18 18:00:00 PST. The current time is Thursday, 15-Feb-18 13:46:35 PST.",

"type": "OAuthException",

"code": 190,

"error_subcode": 463,

"fbtrace_id": "H2il2t5bn4e"

}

}

通常情況下,錯誤內容就是需要在瀏覽器或移動端顯示的內容。因此最好根據需要提供盡可能的細節。

現在,讓我們了解如何更好地改善 API 的錯誤提示。

提示1.即使在本地也要切換 APP_DEBUG=false

Laravel 的 .env 文件有一個重要的設置 APP_DEBUG ,它的值可以為 false or true。

如果設置為 true, 則將顯示所有錯誤以及詳細信息,包括類名稱,數據庫表等。

image

這是一個巨大的安全問題,因此在生產環境中,強烈建議將其設置為 false。

但是,我建議即使在本地也要針對 API 項目將其關閉,原因如下。

關閉實際錯誤后,您將被迫像 API 使用者那樣思考,因為他們只會收到服務器錯誤(返回 Server error)而沒有更多的信息。換句話說,這時候你就需要考慮如何處理錯誤并提供合適的響應消息。

提示2:未處理的路由-回退方法

第一種情況-如果有人調用不存在的 API 怎么辦,有人甚至在 URL 中輸入錯誤的地址。默認情況下,您從 API 獲得以下響應:

Request URL: http://q1.test/api/v1/offices

Request Method: GET

Status Code: 404 Not Found

{

"message": ""

}

至少 404 響應成功。其實可以做得更好,可以通過一些消息來解釋錯誤。

為此你可以在 routes/api.php 的末尾指定 Route::fallback() 方法, 處理所有訪問不存在路由的請求。

Route::fallback(function(){

return response()->json([

'message' => 'Page Not Found. If error persists, contact info@website.com'], 404);

});

結果還是相同的404響應,但現在出現了錯誤消息,提供了有關如何處理此錯誤的更多信息。

提示3.覆蓋404 ModelNotFoundException

最常見就是找不到某些模型對象,通常由 Model :: findOrFail($ id) 拋出。以下是你的 API 會顯示的典型消息:

{

"message": "No query results for model [App\\Office] 2",

"exception": "Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException",

...

}

這是正確的,但向最終用戶顯示的消息不是很漂亮,因此,我的建議是重寫對該特定異常的處理。

我們可以在 app/Exceptions/Handler.php (請記住該文件,我們將在以后多次返回它)中使用 render() 方法:

// Don't forget this in the beginning of file

use Illuminate\Database\Eloquent\ModelNotFoundException;

// ...

public function render($request, Exception $exception)

{

if ($exception instanceof ModelNotFoundException) {

return response()->json([

'error' => 'Entry for '.str_replace('App\\', '', $exception->getModel()).' not found'], 404);

}

return parent::render($request, $exception);

}

我們可以在這種方法中捕獲任意數量的異常。在本例中,我們將返回相同的404代碼,但可讀性更高:

{

"error": "Entry for Office not found"

}

注意: 你有沒有注意到一個有趣的方法?$exception->getModel() ?我們可以從 $Exception 對象中獲得很多非常有用的信息,下面是 PhpStorm 自動完成的屏幕截圖::

image

提示4:在驗證中盡可能多捕獲信息

開發人員一般不會考慮過多的驗證規則,而是堅持使用諸如 required,date,emai 之類的簡單規則。但是對于 API 而言,實際上錯誤的最典型原因是-消費者提交無效數據。

如果我們不花更多的精力來收集未通過驗證的數據,那么 API 將通過后端驗證,并拋出簡單的 Server error,而沒有任何詳細信息(實際上原因是數據庫查詢錯誤)。

讓我們看一下這個示例–我們在 Controller 中有一個 store() 方法:

public function store(StoreOfficesRequest $request)

{

$office = Office::create($request->all());

return (new OfficeResource($office))

->response()

->setStatusCode(201);

}

我們的 FormRequest 文件 app/Http/Requests/StoreOfficesRequest.php 包含兩個規則:

public function rules()

{

return [

'city_id' => 'required|integer|exists:cities,id',

'address' => 'required'

];

}

如果我們遺漏了這兩個參數并在其中傳遞空值,API 將返回一個相當易讀的錯誤,帶有 **422 ** 狀態碼(此狀態碼默認是由于 Laravel 驗證失敗而產生):

{

"message": "The given data was invalid.",

"errors": {

"city_id": ["The city id must be an integer.", "The city id field is required."],

"address": ["The address field is required."]

}

}

它列出了所有字段錯誤,還提到了每個字段的所有錯誤,而不僅僅是捕獲到的第一個錯誤。

現在,如果我們不指定那些驗證規則并允許驗證通過,以下是 API 返回:

{

"message": "Server Error"

}

僅僅是服務器錯誤,沒有其他有用的信息,什么是錯誤的,什么字段是缺失或不正確的。因此 API 使用者會懵逼。

所以我將在這里重復我的觀點-請嘗試在驗證規則中捕獲盡可能多的可能情況。檢查字段是否存在、類型、最小-最大值、重復等

提示5 通常使用 Try-Catch 可以避免空的 500 服務器錯誤

繼續上面的示例,使用 API 時,最糟糕的事情就是空錯誤。但是任何事情都會出錯,尤其是在大型項目中,我們無法修復或預測隨機錯誤。

想象一下這個控制器代碼:

public function store(StoreOfficesRequest $request)

{

$admin = User::find($request->email);

$office = Office::create($request->all() + ['admin_id' => $admin->id]);

(new UserService())->assignAdminToOffice($office);

return (new OfficeResource($office))

->response()

->setStatusCode(201);

}

這是一個虛構的例子,也很常見。用電子郵件搜索用戶,然后創建一條記錄,對該記錄進行操作。并且在任何步驟上,都可能發生錯誤。電子郵件可能為空,可能找不到管理員(或發現錯誤的管理員),服務方法可能會引發任何其他錯誤或異常等。

有很多處理和使用 try-catch 的方法,但是最流行的方法之一就是只捕獲一個大的try-catch,然后對應是哪個異常類拋出的:

try {

$admin = User::find($request->email);

$office = Office::create($request->all() + ['admin_id' => $admin->id]);

(new UserService())->assignAdminToOffice($office);

} catch (ModelNotFoundException $ex) { // User not found

abort(422, 'Invalid email: administrator not found');

} catch (Exception $ex) { // Anything that went wrong

abort(500, 'Could not create office or assign it to administrator');

}

這樣,我們可以隨時調用 abort() 并添加所需的錯誤消息。如果我們在每個控制器(或其中的大多數控制器)中執行此操作,那么我們的 API 將返回與 Server error 相同的500,但包含更多可操作的錯誤消息。

提示6 通過捕獲異常來處理第三方 API 錯誤

如今,Web 項目使用大量外部 API,它們也可能會失敗。如果他們的 API 不錯,那么他們將提供適當的異常和錯誤機制,因此我們需要在應用程序中使用它。

例如,對某些 URL進行 Guzzle curl 請求并捕獲異常。

代碼很簡單:

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle123456');

// ... 用該響應做點什么

您可能已經注意到,Github URL 無效,并且該存儲庫不存在。而且,如果我們將代碼保持原樣,我們的 API 將拋出 500 Server error,沒有其他詳細信息。但是我們可以捕獲異常,并向消費者提供更多詳細信息:

// 在頂部

use GuzzleHttp\Exception\RequestException;

// ...

try {

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle123456');

} catch (RequestException $ex) {

abort(404, 'Github Repository not found');

}

提示6.1 創建自己的異常

我們甚至可以更進一步,創建我們自己的異常,特別是與一些第三方 API 錯誤相關的異常。

php artisan make:exception GithubAPIException

然后,我們新生成的文件 app/Exceptions/GithubAPIException.php將如下所示:

namespace App\Exceptions;

use Exception;

class GithubAPIException extends Exception

{

public function render()

{

// ...

}

}

我們甚至可以讓它為空,但還是把它當作異常拋出。即使是異常 name,也可以幫助 API 用戶避免將來的錯誤。所以我們這樣做:

try {

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle123456');

} catch (RequestException $ex) {

throw new GithubAPIException('Github API failed in Offices Controller');

}

不僅如此-我們可以將錯誤處理移至 app / Exceptions / Handler.php 文件中(還記得上面嗎?),如下所示:

public function render($request, Exception $exception)

{

if ($exception instanceof ModelNotFoundException) {

return response()->json(['error' => 'Entry for '.str_replace('App\\', '', $exception->getModel()).' not found'], 404);

} else if ($exception instanceof GithubAPIException) {

return response()->json(['error' => $exception->getMessage()], 500);

} else if ($exception instanceof RequestException) {

return response()->json(['error' => 'External API call failed.'], 500);

}

return parent::render($request, $exception);

}

最后的注意事項

以上就是我處理 API 錯誤的技巧,但這不是嚴格的規則。每個人都可以有自己的想法,如果你有自己的一些看法,可以在下面發表評論并進行討論。

最后,除了錯誤處理之外,我想鼓勵你做兩件事:

為用戶提供詳細的 API 文檔,請使用類似如下的包 API Generator;

返回 api 錯誤時,使用第三方服務 Bugsnag / Sentry / Rollbar。它們不是免費的,但是在調試時可以節省大量時間。

總結

以上是生活随笔為你收集整理的api laravel 统一返回方法_Laravel API 错误处理:当异常时,如何返回消息的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。