バリデーション

Tag:

Laravelでバリデーションを設定する方法について取り上げます。

設定方法

Controllerのvalidateメソッドでバリデーションを設定

App\Http\Controllers\Controllerクラスで、ValidatesRequestsトレイトを取り込んでいます。このValidatesRequestsトレイト内のvalidateメソッドを利用してバリデーションを設定できます。

class XxxController extends Controller
{
    public function store(Request $request)
    {
        $this->validate($request, [
            'name' => 'required',
            'old' => 'required|max:120|integer'
        ]);
    }
}

ただし、Controllerでバリデーションを設定するとファットコントローラになるので、次に紹介する方法でバリデーションを設定したほうが良いかと思います。

Requestクラスのrulesメソッドで設定

App\Http\Requests\Requestクラスを継承したクラスファイルを生成します。

php artisan make:request XxxRequest

生成されたファイルです。

<?php

namespace App\Http\Requests;

use App\Http\Requests\Request;

class XxxRequest extends Request
{
    /**
     * 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 [
            'name' => 'required',
            'old' => 'required|max:120|integer'
        ];
    }
}

authorizeメソッドに認証ロジックを記述できます。リクエストを受け付けない場合、falseを返します。falseの場合、403を返します。

rulesメソッドにバリデーションを設定します。

コントロールのメソッドに作成したリクエストをタイプヒントで指定することで、バリデーションが行われます。

class XxxController extends Controller
{
    public function store(XxxRequest $request)
    {
    }
}

HTTPメソッドによってバリデーションを変更

リソース作成時(POST)と更新時(PUT)でバリデーション設定を変更したい場合があります。そういったときは、次のようにすると読みやすいかと思います。

public function rules()
{
    $rules = [
        // 共通ルール
    ];

    // 各メソッドごとのルール
    switch($this->method()) {
        case 'POST':
            $rules['xxx'] = 'xxx'; 
            break;
        case 'PUT':
            break;
        case 'DELETE':
            break;
        default:
            break;
    }
    return $rules;
}

バリデーション失敗時

バリデーションに失敗すると例外が発生します。

HTTPリクエストの場合
以前のページにリダイレクトします。このときバリデーションエラー内容はフラッシュデータとして保存されます。リダイレクトで以前のページにアクセスした際に、$errors変数を通じて保存されたエラー内容にアクセスできます。

AJAXリクエストの場合
422HTTPステータスコードでJSONレスポンスが送られます。

View上でエラー内容と直前入力データにアクセス

oldヘルパー関数を通じて、直前入力データにアクセスできます。
$errors変数を通じて、バリデーションエラーにアクセスできます。

<input type="text" name="name" value="{{ old('name', $userdata->name) }}">

@if ($errors->has('name'))
<span class="text-danger">
    <strong>{{ $errors->first('name') }}</strong>
</span>
@endif
1行目
oldヘルパー関数の第2引数には、直前入力データが設定されてないときの値を設定できます。
3~7行目
エラーが設定されていれば、エラーメッセージを表示してます。

エラーメッセージの指定

言語ファイルで指定可能です。日本語であれば、「resources/lang/ja/validation.php」で調整します。

下記内容を調整できます。

  • ルールごとのバリデーションメッセージ
  • 「特定属性」の「特定ルール」にだけ指定するバリデーションメッセージ(custom配列で指定)
  • 属性の日本表示(attributes配列で指定)

属性の日本語表示での注意

formのname属性に指定する名称をDB上のカラム名と同一名称にすることが多いかと思います。

例えば、「usersテーブルのnameカラム」と「productsテーブルのnameカラム」で両方ともformのname属性に「name」と指定し、「resources/lang/ja/validation.php」内のattributes配列に次のように指定しているとします。

    'attributes' => [
        'name' => 'ユーザー名',
    ],

すると、「productsテーブルのnameカラム」でもバリデーションメッセージとして「ユーザー名は必ず指定してください」と表示されてしまいます。

この場合、対象のRequestクラスのattributesメソッドをオーバライドすると良いです。

    public function attributes()
    {
        return [
            'name' => '商品名',        
        ];
    }

同様に、特定ルールのメッセージを変更したい場合として、messagesメソッドもよく使います。

バリデーションの指定

主なバリデーションの指定方法について取り上げます。

ルール 概要
required 入力必須

※特定条件時だけ入力必須にもできる
required_if:他のフィールド,値,...
他のフィールドが値のどれかと一致している場合

required_unless:他のフィールド,値,...
他のフィールドが値のどれとも一致していない場合

required_with:foo,bar,...
指定した他のフィールドが一つでも存在している場合

required_with_all:foo,bar,...
指定した他のフィールドがすべて存在している場合

required_without:foo,bar,...
指定した他のフィールドのどれか一つでも存在していない場合

required_without_all:foo,bar,...
指定した他のフィールドがすべて存在していない場合
integer 整数値(-2や3。1ずつきざむ値)であること
numeric 数値(小数なども含む)であること
email メールアドレスの形式であること
url urlの形式であること
image ファイルが画像(jpg、png、bmp、gif、svg)であること
mimes:jpeg,png,gif ファイル形式が指定形式のどれかと一致すること
date 日付であること
before:日付
after:日付
指定した日付以前/以降であること。日付には、日付文字列(tomorrowなど)を利用できます。日付文字列については、「PHP : 日付操作 | DN-Web64」内で取り上げています。
max:値
min:値
指定された値以上/以下であること。文字列、数値、ファイルで利用可能。
between:min,max 指定された最小値と最大値の間のサイズであること
in:foo,bar fooまたは、barであること。マルチバイト文字列では利用しない。
accepted yes、on、1、trueであること。利用規約同意などで利用。
unique:users,email 「usersテーブル」の「emailカラムのデータ」に同一値がないこと

更新時には、所有者自身のレコードを除外して、同一値が存在するか判定したいです。その場合、以下のようにできます。

'email' => 'unique:users,email,'.$user->id.',user_id'

「usersテーブル」の「user_id」が「$user->id」のレコードを除外して、「emailカラムのデータ」に同一値がないことを判定してくれます。第4引数は、主キーがid以外の時だけ指定します。

exists:users,email 「usersテーブル」の「emailカラムのデータ」に同一値が存在すること
confirmed パスワード入力確認フォームに対して利用。
regex:正規表現 指定された正規表現にマッチすること。正規表現にパイプ(|)を含む場合、パイプ区切りでルールを指定する方法ではなく、配列でルールを指定すること。

$word = array('英語', '国語', '算数');

// 下記指定は、NG
$this->validate($request, [
    'word' => 'string|regex:/^' . implode("|", $word) . '$/'
]);

// 次のように配列で指定する。
$this->validate($request, [
    'word' => ['string', 'regex:/^' . implode("|", $word) . '$/']
]);
alpha_num alpha系ルールには注意。alpha_numのルールは、全部アルファベット文字と数字であることですが、マルチバイト文字も受け付けてしまいます。半角英数だけに制限したいとき、下記のように正規表現を利用します。

regex:/^[a-zA-Z0-9]+$/

新たに、上記正規表現で判定するカスタムバリデーションを追加して利用するのも良いかと思います。

その他のルールや詳しい説明は、下記URLが参考になります。
⇒ https://readouble.com/laravel/5.1/ja/validation.html#available-validation-rules

スポンサーリンク