13. FormRequest
バリデーション
validate(バリデート)とは
validate(バリデート)は、入力データが正しいかプログラミングで検証する仕組みです。 DBにレコード更新する前にプログラムでバリデートして、事前にデータの不整合を防ぎます。
バリデートしない場合
バリデートせずにデータを更新しようとすると、入力必須のカラムがあるためSQLエラーが発生します。
public function add(ItemRequest $request)
{
$posts = $request->all();
//POSTデータをチェック
if ($posts['name'] && $posts['price'] > 0 && ...) {
Item::create($posts);
}
return redirect()->route('admin.item.index');
}
FormRequestファサード
FormRequestファサードとは
FormRequestファサードを利用すると、リクエスト受信時に事前処理(バリデートなど)するのに便利です。
FormRequestファイル作成
artisan make:requestで、ItemRequestを作成します。
ターミナル
php artisan make:request ItemRequest
authorize()
「ItemRequest」を作成したら authorize() の結果を trueで設定します。falseだとリクエストに対してバリデーションをしません。
ItemRequest.php
class ItemRequest extends FormRequest
{
public function authorize()
{
//return false;
// true に変更
return true;
}
...
}
rules()
rules() にバリデーションの設定をします。データ形式は、「カラム名」「バリデーションタイプ」の連想配列です。
public function rules()
{
return [
カラム名 => バリデーションタイプ,
];
}
バリデーションタイプ
バリデーションタイプはいくつかありますが、今回の例では以下のようになります。
バリデーションタイプ | 動作 |
---|---|
required | 入力必須 |
string | 文字列 |
integer | 整数 |
min:数値 | 最小値 |
unique | 重複 |
複数のバリデーションタイプ
バリデーションタイプが複数あるときは配列または、| (パイプ)で設定します。
配列
['required', 'min:0', 'integer']
| (パイプ)
'required|min:0|integer'
レコードを除外
unique() と ignore()
unique() と ignore() で自レコードを更新しないように、レコードを除きます。
Rule::unique(テーブル名)->ignore(重複カラム)
以下のようなSQLの条件が追加されます。
SQL
... WHERE カラム = 'xxxx' AND 重複チェックカラム <> 'xxxx'
ItemRequestの作成
FormRequest ファイルの作成
「ItemRequest」を作成します。
ターミナル
php artisan make:request ItemRequest
ファイル確認
「app/Http/Requests/」に「ItemRequest.php」が作成されました。
authorize() の有効
「ItemRequest」の authorize() で、trueを返すように変更します。
ItemRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ItemRequest extends FormRequest
{
public function authorize()
{
//return false;
// true に変更
return true;
}
public function rules()
{
return [
];
}
}
バリデーションの実装
ファサード追加
「ItemRequest」にRuleファサードを読み込みます。
ItemRequest.php
use Illuminate\Validation\Rule;
Langファサード
「ItemRequest」にLangファサードを読み込みます。
ItemRequest.php
use Illuminate\Support\Facades\Lang;
rules() の設定
rules() にバリデーションを設定します。
public function rules()
{
return [
'name' => ['required', 'string'],
'price' => ['required', 'min:0', 'integer'],
];
}
- name: 文字列で入力必須
- price: 整数値で「0」以上
コントローラーの設定
メソッドインジェクション
store() の引数を「ItemRequest」に変更(メソッドインジェクション)すると、store() が実行される前にバリデーションが処理されます。
ItemController.php
public function store(ItemRequest $request)
{
$posts = $request->all();
Item::create($posts);
return redirect()->route('item.index');
}
スニペット
「itemr」でスニペット入力すると、ItemRequest が自動的にインポートされます。
ItemController.php
use App\Http\Requests\ItemRequest;
バリデートの確認
商品入力画面で未入力で送信すると、自動的に入力画面に戻ります。
送信前のデータ表示
商品入力画面
old() で前回入力のデータを取得し、入力画面のテキストフィールドに表示します。
<input type="text" class="form-control" name="name" value="{{ old('name') }}">
create.blade.php
<h2>新規商品</h2>
<div>
<form action="{{ route('item.store') }}" method="post">
@csrf
<div class="form-group mb-3">
<label for="" class="form-label">商品名</label>
<input type="text" class="form-control" name="name" value="{{ old('name') }}">
</div>
<div class="form-group mb-3">
<label for="" class="form-label">価格</label>
<input type="number" class="form-control" name="price" value="{{ old('price') }}">
</div>
<div>
<button class="btn btn-primary w-100">更新</button>
</div>
</form>
</div>
演習
問題1
ItemController->update() で、ItemRequest を実装してみましょう。