【Laravel】FormRequestクラスを使ってカスタムバリデーション

もくじ

Laravelでバリデーション

Laravelで入力チェックを実装するには、Requestを使います。

POSTリクエストで入力された値を簡単にバリデーションチェックできます。

Requestクラス

まずはFormRequestクラスを使わず、Laravelが初めから用意しているRequestクラスを使って簡単にバリデーションしてみます。

ルーティング

Route::get('/request', 'PostController@create')->name('request');
Route::post('/request', 'PostController@store');

ビュー

<form action="{{ route('request') }}" method="POST">
  @csrf
  
  <div class="form-group">
    <label for="title" class="col-form-label">タイトル</label>
    <input type="text" class="form-control" id="title" name="title" placeholder="タイトル" value="{{ old('title') }}"/>
    @error('title')
      <div class="text-danger">{{ $message }}</div>
    @enderror
  </div>

  <div class="form-group">
    <label for="body" class="col-form-label">本文</label>
    <textarea type="text" class="form-control @error('body') is-invalid @enderror" id="body" name="body" placeholder="本文">{{ old('body') }}</textarea>
    @error('body')
      <div class="text-danger">{{ $message }}</div>
    @enderror
  </div>

  <div class="form-group row justify-content-center">
    <button type="submit" class="btn btn-primary">送信</button>
  </div>
</form>

inputタグ

<input 
  type="text" 
  class="form-control @error('title') is-invalid @enderror" 
  id="title" 
  name="title" 
  placeholder="タイトル" 
  value="{{ old('title') }}"
/>

わかりやすいように改行しています。

name属性は、バリデーションするinputタグを識別するので必須です。

old関数

value属性にあるold関数は、入力値がもしバリデーションに引っかかってエラーになった時に値を維持しておくためのものです。仮にold関数を設置しなかった場合、エラーになるたびに入力した値は空になります。

Laravelではoldグローバルヘルパ関数も用意しています。とくにBladeテンプレートで直前の入力値を表示したい場合に、oldヘルパは便利です。指定した文字列の入力が存在していないときは、nullを返します。

参考:HTTPリクエスト 7.x Laravel

エラーメッセージの表示

@error('title')
  <div class="text-danger">{{ $message }}</div>
@enderror

エラーになったときに表示するメッセージを設置します。

@error('title')

name="title"inputがエラーになった時

{{ $message }}

ここにエラーメッセージが表示されます。

スタイルの変更

f:id:bonoponz:20201030213440p:plain

今はエラーになるとメッセージが文字と枠線が赤色になるだけですが、クラスを変更してスタイルを簡単に変更できます。

class="form-control @error('title') is-invalid @enderror" // これを
class="form-control" // これに変更

f:id:bonoponz:20201030202055p:plain

エラーになっても枠線は赤くなりません。

<div class="alert alert-danger">{{ $message }}</div> // 変更

f:id:bonoponz:20201030202140p:plain

エラーメッセージをボックスのように変更もできます。

コントローラー

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class PostController extends Controller
{
  public function create()
  {
    return view('/request');
  }

  public function store(Request $request)
  {
    // バリデーション実行
    $request->validate([
      'title' => 'required|max:5',
      'body' => 'required',
    ]);
  }
}

Requestクラスの使用

public function store(Request $request)

storeメソッドの引数にRequestクラスを指定し、入力された値を格納します。

$requestformタグで入力した値が全て入っています。

use宣言

use Illuminate\Http\Request;

Requestクラスを使うには必ずはじめにuse宣言しておきましょう。

バリデーション実行

$request->validate([
  'title' => 'required|max:5',
  'body' => 'required',
]);

左辺がinputname属性を指定し、右辺がバリデーションのルールを指定します。

  • required : 入力必須
  • max : 最大数

他にもLaravelは多様なルールを用意してくれています。

公式ドキュメントを確認して使ってみましょう。

カスタマイズ

FormRequestクラスを使うことによって、バリデーションをカスタマイズできます。

controllerでのvalidate()が不要になり、エラーメッセージもカスタマイズできるので日本語化もできます。

詳しくは後述します。すぐ読みたい場合はFormRequestクラスから。

ブラウザで確認

初期表示

f:id:bonoponz:20201030194446p:plain

バリデーション実行

f:id:bonoponz:20201030213945p:plain

FormRequestクラス

ではFormRequestクラスを使うとどうなるか比較してみます。

ファイル作成

FormRequestクラスのファイルを作成します。

$ php artisan make:request StoreBlogPost
Request created successfully.

successfullyと出れば成功です。

make:requestコマンドを実行するとapp/Http/Requestディレクトリが生成され、そこにファイルが設置されます。すでにディレクトリが存在する場合は内包されます。

ルーティングとビュー

これはFormRequestクラスを作る前と同じで大丈夫です。

リクエス

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreBlogPost extends FormRequest
{
  public function rules()
  {
    return [
      'title' => 'required|max:5',
      'body' => 'required',
    ];
  }
  
  public function messages()
  {
    return [
      'title.required' => 'タイトルは必須です',
      'title.max' => 'タイトルは5文字までです',
      'body.required' => '本文は必須です',
    ];
  }
}

コントローラー

<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreBlogPost;

class PostController extends Controller
{
  public function create()
  {
    return view('/request');
  }

  public function store(StoreBlogPost $request)
  {
    // バリデーションの記述は不要
  }
}

use宣言

use App\Http\Requests\StoreBlogPost;

先ほど作ったStoreBlogPostをuse宣言します。これがないと、エラーになりますので忘れずに。

StoreBlogPostクラスの使用

public function store(StoreBlogPost $request)

storeメソッドの引数にStoreBlogPostクラスを指定します。

これにより$requestに格納された入力値はコントローラメソッドが呼び出される前にバリデーションを行います

よって、コントローラーの中でバリデーションの処理を記述する必要がなくなります。(もちろん、記述することも可能です)

入力した値の取得

f:id:bonoponz:20201030204649p:plain

これで検証してみます。

入力値を全て取得

$request->all()
// array(3) { ["_token"]=> string(40) "(トークン)" ["title"]=> string(9) "あああ" ["body"]=> string(9) "いいい" } 

トークンも取得できます。

指定のinputを取得

$request->title
$request['title']
$request->input('title')

入力された値を使って何かしらの処理をしたいときは、上記のコードを使って入力値を使用できます。

なお、いずれも入力値が取得できます。

echo($request->title);
// 結果:あああ
echo($request['title']);
// 結果:あああ
echo($request->input('title'));
// 結果:あああ

存在チェック

$request->has('title')
// 結果は真偽値

結果が真偽値なので、if文などで活躍します。

if ($request->has(['title'])) {
  $title = $request->title;
  echo($title . "と入力されました。");
}
// 結果:あああと入力されました。

除外

$request->except(['title'])
// array(2) { ["_token"]=> string(40) "(トークン)" ["body"]=> string(9) "いいい" }

name="title"以外の入力値とトークンを取得できます。

ほかにもあるので、公式ドキュメントで確認してみてください。

参考URL

バリデーション 7.x Laravel

HTTPリクエスト 7.x Laravel

Laravel : FormRequestクラスを使ってValidation(MyMemo) - Qiita