5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Laravel 複雑なバリデーションでフォームリクエストクラスを使用する

Posted at

概要

  • フォーム送信されたときにバリデーションメソッドを使って各項目が適正であるかをチェックする
  • Laravelでデフォルトで用意されたバリデーション内容では満足できない複雑なバリデーションを必要とするとき、コントローラへの記載ではコントローラーが肥大化し、可読性が落ちる。そこで、フォームリクエストクラスというバリデーションロジックをコントローラから分離させる。

内容

今回はFFromRequestクラスを継承したSampleRequestクラスを生成し、コントローラからのバリデーション分離を試みる。

フォームリクエストクラスの生成

下記コマンドを実行

$ php artisan make:request SampleRequest

するとapp/Http/Request下にSampleRequest.phpが生成される

app/Http/Request
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class SampleRequest extends FormRequest
{
    /**
     * 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 [
            //
        ];
    }
}

生成されたファイルを次のように編集していく

  • authorize()ではtrueを返す
    • authorize()はユーザ権限や認証系のバリデーションを定義する
    • 特に必要ない場合はfalseを返す
  • rules()にバリデーション内容を記載する
app/Http/Request
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class SampleRequest 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 [
          'name' => 'required|string|max:255',
          'gender' => 'required',
          'age' => 'required|integer',
          'file' => 'required|file|image|max:10000',
          'comment' => 'required',
        ];
    }
}

コントローラ側の設定

フォームリクエスト使用に伴い、下記2点を追加する

  • 生成したSampleRequestをuseする
  • アクション名の引数にSampleRequsetを渡す
    • フォーム内容がアクションへ渡される際にバリデーション処理が実行され、渡ってきた際にはバリデーション処理が完了している状態である
app/Http/Controllers/SampleController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests\SampleRequest;  // 追記

class ValiController extends Controller
{
  public function update(SampleValiRequest $request)  // 引数にフォームリクエスト渡す
  {
        return view('sample');
 }
}

カスタムエラーメッセージ設定

  • フォームごとに独自のエラーメッセージを表示したい場合、フォームリクエストクラスに追記するだけで実装できる
  • messages()を作成し、その中にエラーメッセージ内容を記述する
    • name.ruleの規則で記述する
app/Http/Request
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class SampleRequest 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 [
          'name' => 'required|string|max:255',
          'gender' => 'required',
          'age' => 'required|integer',
          'file' => 'required|file|image|max:10000',
          'comment' => 'required',
        ];
    }
    
    // 追記内容
    /**
     * エラーメッセージのカスタマイズ
     * @return array
     */
    public function messages()
    {
      return [
        'name.required' => '名前を入力してください',
        'name.string' => '名前は文字列で入力してください',
        'name.max' => '名前は255文字以内で入力してください',
        'gender.required'  => '性別を選択してください',
        'age.required'  => '年齢を選択してください',
        'age.integer'  => '年齢は数字で入力してください',
        'file.required'  => 'ファイルを選択してください',
        'file.file'  => 'ファイルのアップロードに失敗しました',
        'file.image'  => 'アップロード可能な画像は「jpg」「png」「bmp」「gif」「svg」です',
        'file.max'  => 'アップロードするファイルは10MBまでです',
        'comment.required' => 'コメントを入力してください',
      ];
    }
    
}

独自バリデーションの追加

  • 上記に引き続きフォームリクエスト内に追記する形で実装
  • withValidator()メソッドに処理内容を記載することでバリデーション追加をすることが可能
    • validatorの中に
app/Http/Request
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class SampleRequest 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 [
          'name' => 'required|string|max:255',
          'gender' => 'required',
          'age' => 'required|integer',
          'file' => 'required|file|image|max:10000',
          'comment' => 'required',
        ];
    }
    
    /**
     * エラーメッセージのカスタマイズ
     * @return array
     */
    public function messages()
    {
      return [
        'name.required' => '名前を入力してください',
        'name.string' => '名前は文字列で入力してください',
        'name.max' => '名前は255文字以内で入力してください',
        'gender.required'  => '性別を選択してください',
        'age.required'  => '年齢を選択してください',
        'age.integer'  => '年齢は数字で入力してください',
        'file.required'  => 'ファイルを選択してください',
        'file.file'  => 'ファイルのアップロードに失敗しました',
        'file.image'  => 'アップロード可能な画像は「jpg」「png」「bmp」「gif」「svg」です',
        'file.max'  => 'アップロードするファイルは10MBまでです',
        'comment.required' => 'コメントを入力してください',
      ];
    }
    
 
 // 追記内容
 
  /**
   * 独自処理を追加する
   * @param $validator
   */
  public function withValidator($validator)
  {
    $validator->after(function ($validator) {
      if (
        strtotime(date('H:i:s')) >= strtotime('21:00:00')
        ||
        strtotime(date('H:i:s')) <= strtotime('09:00:00')
      ) {
        $validator->errors()->add('field', '投稿できるのは9時から21時までです。');
      }
    });
  }
    
}

参考

5
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?