こんにちは、JeffTechです。
説明
LaravelでAPIを作成している際に、リクエストの中に配列が混ざっているものを必須バリデーションさせる方法を説明します。
下記のようなリクエストがJSON形式で飛んできたことを想定していきます。
{
"app": {
"posts": [
{
"post": {
"id": "3",
"count": "10"
}
}
]
}
}
この記事で実現できること
- 配列のバリデーションを実装することができる
開発環境
- OS: MacOs
- PHP: 7.3
- Larave: 6.2
実装の流れ
- Laravelプロジェクトの作成
- 日本語化
- Controllerの作成&編集
- Requestの作成&編集
- テスト
実装
Laravelプロジェクトの作成
まずはLaravelをインストールしちゃいます。
$ composer create-project --prefer-dist laravel/laravel api_array_validation '6.*'
日本語化
エラーメッセージを日本語で出力したいので、下記コマンドでresources/lang/ja
ファイルを作成してください。
$ php -r "copy('https://readouble.com/laravel/6.x/ja/install-ja-lang-files.php', 'install-ja-lang.php');"
$ php -f install-ja-lang.php
$ php -r "unlink('install-ja-lang.php');"
デフォルトでは英語のresources/lang/en
ファイルが使用されるようになっていますが、config/app.php
で日本語用のファイルを使用するように設定しましょう。
<?php
return [
ーー省略ーー
/*
|--------------------------------------------------------------------------
| Application Locale Configuration
|--------------------------------------------------------------------------
|
| The application locale determines the default locale that will be used
| by the translation service provider. You are free to set this value
| to any of the locales which will be supported by the application.
|
*/
'locale' => 'ja',
ーー省略ーー
]
Controllerの作成&編集
今回使用するコントローラの作成です。
$ php artisan make:controller PostController
$requestを受け取って、バリデーションが通れば成功と出力する簡単なものにします。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\PostRequest;
class PostController extends Controller
{
public function index(PostRequest $request)
{
$request = $request->all();
dd('成功');
}
}
Requestの作成&編集
バリデーションを設定するためにフォームリクエストを作成していきます。
$ php artisan make:request PostRequest
バリデーションを実装していきます。
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class PostRequest 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 [
'app.posts' => 'required',
'app.posts.*.post.id' => 'required|integer',
'app.posts.*.post.count' => 'required|integer',
];
}
/**
* エラーメッセージを出力
*
* @return viod
*/
protected function failedValidation(Validator $validator)
{
$response['errors'] = $validator->errors()->toArray();
throw new HttpResponseException(
response()->json($response, 422, [], JSON_UNESCAPED_UNICODE,)
);
}
/**
* エラーメッセージを変更
*
* @return array
*/
public function messages()
{
return [
'application.menus.*.menu.id.required' => ':attributeは必ず指定してください。',
'application.menus.*.menu.count.required' => ':attributeは必ず指定してください。',
];
}
/**
* エラー用文言を設定
*
* @return array
*/
public function attributes()
{
return [
'application.menus.*.menu.id' => 'application.menus.*.menu.id',
'application.menus.*.menu.count' => 'application.menus.*.menu.count',
];
}
}
これで実装自体は終わりです。
Response::json()の第4引数に、JSON_UNESCAPED_UNICODE
を設定すると、unicodeで日本語をエスケープせずにそのまま返してくれます。
'app.posts' => 'required',
で配列自体にバリデーションをかけて、
'app.posts.*.post.id' => 'required|integer',
'app.posts.*.post.count' => 'required|integer',
で各要素にバリデーションをかけていきます。
エラーメッセージを出力する処理やmessagesメソッド、attributesメソッドはトレイトとかで共通化するともっと楽になりそうです。
実装したい場合はこちらを御覧ください。
テスト
今回私はinsomniaを使用してテストを行っていきます。
insomniaって何!って人はPostmanを想像してください。
insomniaめちゃ良いので、よかったらこちらからインストールください。
$ php artisan serve
で簡易サーバーを起動して、insomniaにてGETでhttp://127.0.0.1:8000/api/validate
を叩いてみると、しっかりと下記のようなエラーメッセージが出力されると思います。
postなしの場合
{
"app": {
}
}
{
"errors": {
"app.posts": [
"app.postsは必ず指定してください。"
]
}
}
idとcountなしの場合
{
"app": {
"posts": [
{
"post": {
}
}
]
}
}
{
"errors": {
"app.posts.0.post.id": [
"app.posts.0.post.idは必ず指定してください。"
],
"app.posts.0.post.count": [
"app.posts.0.post.countは必ず指定してください。"
]
}
}
idとcountが文字の場合
{
"app": {
"posts": [
{
"post": {
"id": "aaa",
"count": "aaa"
}
}
]
}
}
{
"errors": {
"app.posts.0.post.id": [
"app.posts.0.post.idは整数で指定してください。"
],
"app.posts.0.post.count": [
"app.posts.0.post.countは整数で指定してください。"
]
}
}
正常時
正常な値が送られている時には、コントローラで設定した成功
と出力されます。
{
"app": {
"posts": [
{
"post": {
"id": "1",
"count": "10"
}
}
]
}
}
"成功"
最後に
少しでも役に立った!という時は、いいねをポチッとして
フォローしてくださると嬉しいです、、、笑
役に立たなかった時は、怒らないでコメント頂けますと幸いです笑
Twitterもやってますので、よかったら見てみてくださいね!
https://twitter.com/jefftechsaku