Laravel框架表單驗證格式化輸出

  • 2019 年 10 月 7 日
  • 筆記

老規矩,點擊底部左下角閱讀原文,隨時了解文章更新內容.

問題背景

最近在公司的項目開發中使用到了 laravel 框架,採用的是前後端開發的模式。接觸過前後端開發模式的小夥伴應該都知道,後端返回的數據格式需要儘可能搞得保證一致性,這樣前端在處理時也方便處理。我們先通過觀看下面的兩張接口返回的效果圖吧,這樣或許會更加的直觀一些

laravel默認的輸出格式(圖一)

修改後的輸出格式(圖二)

或許通過上面兩張圖,你還是未看出有什麼區別的話。這裡我用文字描述一下吧。這種情況是發生在laravel做表單驗證的情況下發生的。前端向我後端接口發送一個POST請求時,發送了一個title和body的字段。我後端需要對兩個字段做一些非空驗證。按照框架手冊來進行的話,輸出的格式就是圖一的格式。然後後端統一的輸出格式是圖二中的格式,如果按照圖一的格式輸出肯定是不行,這樣就需要我們做一個特殊處理。

問題排查

首先我們可以通過文檔參看到如下信息。下面劃線的部分,提到的返回信息是將所有未驗證通過的數據都返回給前端,就如圖一中的數據格式。

laravel默認的輸出格式(圖三)

預期效果

通過圖三我們知道了 laravel 默認的是返回一個帶 422 的 http 狀態碼並且將所有的驗證錯誤信息都返回。然而我們需要的只是如圖二的格式,單個的輸出錯誤信息。大致的解決思路就是在輸出的時候,我們去默認顯示第一個未通過的驗證信息,當通過之後,之前第二個未嚴重通過的就變成了第一個,這樣依次循環下去,我們的每個數據就得到了驗證。驗證的地方我們選擇框架異常統一處理的地方,這樣每次驗證都自動的進行處理。

解決方案

該框架是 laravel5.8 的情況下進行編寫,如果版本不同,或許還需要特殊的處理,不過處理的思路可以參考下面的。

1.創建一個表單驗證器。執行下面的命令之後,我們在 php app/Http/Requests目錄下面就可以看到該類文件了。

php artisan make:request ProjectValidate

2.定義驗證規則。rules 方法是定義驗證規則,而 messages 方法則是定義返回的錯誤信息,該方法也可以省略掉,這樣提示的信息就是英文而不是圖一或圖二看到的中文了。

namespace AppHttpRequests;    use IlluminateFoundationHttpFormRequest;    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 方法中,使用依賴注入的方式去實現數據的驗證。記住,該方法體在未通過數據驗證的情況下是不會去執行的。

namespace AppHttpControllersBackendProject;    use AppHttpRequestsProjectValidate;  use AppHttpControllersBackendUCenter;    class Index extends UCenter  {        public function index()      {          return success();      }        public function addData(ProjectValidate $request)      {          $validated = $request->validated();          return success($validated);      }  }

4.統一處理數據格式。找到 phpAppExceptionsHandler.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 請求。