バリデーション

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 を実装してみましょう。

Laravel超入門