問題背景
最近在公司的專案開發中使用到了 laravel 框架,採用的是前後端開發的模式。接觸過前後端開發模式的小夥伴應該都知道,後端返回的資料格式需要儘可能搞得保證一致性,這樣前端在處理時也方便處理。我們先通過觀看下面的兩張介面返回的效果圖吧,這樣或許會更加的直觀一些。
圖一
圖二
或許通過上面兩張圖,你還是未看出有什麼區別的話。這裡我用文字描述一下吧。
這種情況是發生在laravel做表單驗證的情況下發生的。前端向我後端介面傳送一個POST請求時,傳送了一個title和body的欄位。我後端需要對兩個欄位做一些非空驗證。按照框架手冊來進行的話,輸出的格式就是圖一的格式。然後後端統一的輸出格式是圖二中的格式,如果按照圖一的格式輸出肯定是不行,這樣就需要我們做一個特殊處理。
問題排查
首先我們可以通過文件參看到如下資訊。下面劃線的部分,提到的返回資訊是將<font color='red'>所有未驗證通過的資料都返回給前端,就如圖一中的資料格式。
圖三
預期效果
通過圖三我們知道了 laravel 預設的是返回一個帶 422 的 http 狀態碼並且將所有的驗證錯誤資訊都返回。
然而我們需要的只是如圖二的格式,單個的輸出錯誤資訊。大致的解決思路就是在輸出的時候,我們去預設顯示第一個未通過的驗證資訊,當通過之後,之前第二個未嚴重通過的就變成了第一個,這樣依次迴圈下去,我們的每個資料就得到了驗證。驗證的地方我們選擇框架異常統一處理的地方,這樣每次驗證都自動的進行處理。
解決方案
該框架是 laravel5.8 的情況下進行編寫,如果版本不同,或許還需要特殊的處理,不過處理的思路可以參考下面的。
1.建立一個表單驗證器。執行下面的命令之後,我們在php app/Http/Requests
目錄下面就可以看到該類檔案了。
php artisan make:request ProjectValidate
2.定義驗證規則。rules 方法是定義驗證規則,而 messages 方法則是定義返回的錯誤資訊,該方法也可以省略掉,這樣提示的資訊就是英文而不是圖一或圖二看到的中文了。
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ProjectValidate extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => 'bail|required',
'body' => 'required',
];
}
/**
* define the validation message
*
* @return array
*/
public function messages()
{
return [
'title.required' => '文章標題必填',
'body.required' => '文章內容必填',
];
}
}
3.使用驗證器。這裡我定義了一個控制器,在 addData 方法中,使用依賴注入的方式去實現資料的驗證。<font color='red'>記住,該方法體在未通過資料驗證的情況下是不會去執行的。
namespace App\Http\Controllers\Backend\Project;
use App\Http\Requests\ProjectValidate;
use App\Http\Controllers\Backend\UCenter;
class Index extends UCenter
{
public function index()
{
return success();
}
public function addData(ProjectValidate $request)
{
$validated = $request->validated();
return success($validated);
}
}
4.統一處理資料格式。找到php App\Exceptions\Handler.php
檔案,找到下面的方法,修改為如下內容。這時候在做表單驗證就會顯示圖二的格式資訊了。
public function render($request, Exception $exception)
{
if ($exception instanceof ValidationException) {
// 只讀取錯誤中的第一個錯誤資訊
$errors = $exception->errors();
$message = '';
// 框架返回的是二維陣列,因此需要去迴圈讀取第一個資料
foreach ($errors as $key => $val) {
$keys = array_key_first($val);
$message = $val[$keys];
break;
}
return response()->json(['code' => 1001, 'message' => $message, 'data' => []], 422);
}
return parent::render($request, $exception);
}
總結
1.優勢
輸出固定的格式,前端在處理資料的時候,不需要做特別的格式上面調整。
2.劣勢
這樣的方式驗證,每驗證一次,就會向後端傳送一個 http 請求。