Laravelって、気が付くとcontrollerがひどいことになるよね。MVCの宿命かもしれないけど。
今回はAPIの処理で受け取ったJSONのvalidationをFormRequestを使ってやってみるよ。
下記サイトをバリ参考にしました。ありがとうございます。
Laravelを使ったAPI開発でController内のバリデーションをFormRequestに抽出して幸せになろう
ちなみに環境は下記の通り
Laravel 7.13.0
OS Windows10
開発環境 homestead
DB mysql
1.チェックしたいJSON
こんな感じのデータをチェックするよ。
{
"company_id" : "12345" ,
"company_name" : "corp XXX",
"branches" : [
{"no" : "1",
"branch_code" : "0123",
"branch_name" : "ABC"
}
{"no" : "2",
"branch_code" : "9876",
"branch_name" : "XYZ"
}
]
}
配列の中に更に配列があるパターンだね。
APIでこれをもらってきて、必須チェックとか数字チェックとかするよ。
2.考え方
イメージとして、controllerでJSONを受け取るとき、まさに受け取るところでValidationをかけます。
これは、受け取るときのパラメータの書き方を、通常の(Request $request)から、(《FormRequestの名前》 $request)にして、FormRequestを通ってきたものを使うようにすればよいのです。
public function store (JsonRequest $request)
{
//普通に処理を書いていく
//$reqesutはvalidation実行後のものになる
}
では、FormRequestを書いていこう。
3.FormRequestの中身
まずは例によってartisanでrequestを作成するよ。
今回は「JsonRequest」という名前のrequestを作成します。
php artisan make:request JsonRequest
そうすると、/app/Httpの下に「Requests」というフォルダーが作成され、その中に「JsonRequest.php」が作成される。
<?php
namespace App\Http\Requests;
use Illuminate\contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
class JsonRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}
こんな感じ。
public function authorize()は認証関係のチェックを行う用のfunctionです。
認証なんて何もしないよ!という人はreturnをtrueに変更してください。でないと常にfalseが返ってしまい、いつまでも認証エラーです。
piblic function rules()の中に、validationのルールを書いていきます。
書き方は普通のlaravelのvalidationの書き方と同じです。
公式マニュアルはこちら
今回はこんな風に書いてみました。
companyテーブルは、そういうものがあるつもりで考えてね。
<?php
namespace App\Http\Requests;
use Illuminate\contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
class JsonRequest 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 [
//
'company_id' => 'exists:company,id', //comapnyテーブルの存在チェック
'company_code' => 'numeric', //数字であること
'branches.*.no' => ['numeric', 'distinct'], //数字、かつ重複チェック
'branches.*.branch_code' => 'numeric', //数字であること
];
}
}
普通はこれでいいんだけど、FormRequestは基本画面から呼ばれた前提で処理が作られており、エラーが発生したとき画面にエラーメッセージを返そうとします。
今回はAPIで受け取っているので、エラー情報の返却もJSONで返したい。
なので、レスポンスをJSONで返す処理を追加します。
//public function rulesの後とか、適当なところに追加
protected function failedValidation(Validator $validator)
{
$res = response()->json([
'status' => 400,
'errors' => $validator->errors(),
],400);
throw new HttpResponseException($res);
}
もし独自のチェックをしたいとか、validationでない処理もしたいとか考えているなら、public function withValidatorに$varidator->afterとか追加すれば実現できます。ここでは書かないけど。
ここまで出来たら、最初に書いたようにcontrollerにJsonRequestを追加してください。
// 必要なところだけ抜粋
//最初にJsonRequestを取り込んでね
use App\Http\Requests\JsonRequest;
//途中省略
public function store(JsonRequest $request)
{
//普通に処理を書く
//validateはもう実行済み
}
こうすると、あら不思議。勝手にvalidateされちゃいます。
メッセージの変更の仕方とかは、別の人の記事を探してね。
まずは、めでたしめでたし。