2
1

[Laravel]フォームリクエストバリデーションについて

Last updated at Posted at 2024-02-15

はじめに

ララベルのバリデーション実装時に躓いたので、備忘録も兼てまとめたいと思います。

バリデーションの種類

Laravelのバリデーションは大きく分けて二つあります。

1.validateメソッドを使ってコントローラーに記述する

2.フォームリクエストバリデーション

どちらを使った方がいいのか

時と場合によりますが、特に理由がなければフォームバリデーションを使った方が良い。

理由としてファットコントローラーを避けるため。コントローラーにはなるべくロジックは書きたくないので、分けられるなら分けた方が良い

フォームリクエストバリデーションのファイルはバリデーションの処理しか書かないので分かりやすい。

今回はフォームリクエストバリデーションについてまとめたいと思います

フォームリクエストバリデーションの使い方

下記の簡単なフォームで実装します。
image

まずは下記コマンドでフォームリクエストバリデーションを実装するファイルを作ります。

php artisan make:request StoreEventRequest

そうすると
App\Http\Requests配下にStoreEventRequestが生成されます

コントローラー

1.useでStoreEventRequestを参照する

2.保存処理をするメソッドの引数を、StoreEventRequestにする。

<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreEventRequest;

class EventController extends Controller
{
    // 省略
    public function store(StoreEventRequest $request)
    {
    // 処理
    }
    // 省略
}

フォームリクエストバリデーション

初期表示

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreEventRequest
 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<string, mixed>
     */
    public function rules()
    {
        return [
            //
        ];
    }
}

実装後

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreEventRequest
 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<string, mixed>
     */
    public function rules()
    {
        return [
            'event_name' => ['required', 'max:50'],
            'information' => ['required', 'max:200'],
            'event_date' => ['required', 'date'],
            'start_time' => ['required'],
            'end_time' => ['required', 'after:start_time'],
            'max_people' => ['required', 'numeric', 'between:1,20'],
            'is_visible' => ['required', 'boolean']
        ];
    }

    /**
     * 定義済みバリデーションルールのエラーメッセージ取得
     *
     * @return array<string, string>
     */
    public function attributes(): array
    {
        return [
        'event_name' => 'イベント名',
        'information' =>'イベント詳細',
        'event_date' =>'イベント日付',
        'start_time' =>'開始時間',
        'end_time' =>'終了時間',
        'max_people' =>'定員数',
        'is_visible' =>'表示・非表示'
        ];
    }
/**
 * バリデーションエラーのカスタム属性の取得
 *
 * @return array<string, string>
 */
public function messages(): array
{
    return [
        'event_name.required' => ':attributeを入力してください',
        'event_name.max_length' => ':attributeは50文字以内で入力してください',
        'information.required' =>':attributeを入力してください',
        'event_date.required' =>':attributeを入力してください',
        'start_time.required' =>':attributeを入力してください',
        'end_time.required' =>':attributeを入力してください',
        'max_people.required' =>':attributeを入力してください',
        'is_visible.required' =>':attributeを選択してください'
        ];
}
}

説明

rules()について

rules()には、キーにフォームのname要素、バリューにどんなバリデーションをつけたいか記述する。

    public function rules()
    {
        return [
            'name要素' => どんなバリデーションにするか,
        ];
    }

バリューに関しては色々なレパートリーがある。

attributes()について

messages()の:attributeの名前を指定することが出来ます。

messages()について

rules()で指定したエラーが起きたときに、attributes()で指定した名前でエラーを表示することが出来ます。

bladeでエラーを表示させる方法

フォームの上に下記記述をすることで、エラーをリスト表示することが出来ます

@if ($errors->any())   //エラーがあるか判定
    <div style="color:red" class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li> //エラーを表示
            @endforeach
        </ul>
    </div>
@endif

実際の表示

image

実際のblade

<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            イベント新規登録
        </h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
            <div class="max-w-2xl py-4 mx-auto">
            
                @if ($errors->any())
                    <div style="color:red" class="alert alert-danger">
                        <ul>
                            @foreach ($errors->all() as $error)
                                <li>{{ $error }}</li>
                            @endforeach
                        </ul>
                    </div>
                @endif
               
                 <form method="POST" action="{{ route('events.store') }}">
                     @csrf
                       <div>
                           <x-jet-label for="event_name" value="イベント名" />
                           <x-jet-input id="event_name" class="block mt-1 w-full" type="text" name="event_name" :value="old('event_name')"  />
                       </div>
                       <div class="mt-4">
                           <x-jet-label for="information" value="イベント詳細" />

                           <textarea row="3" id="information" name="information" class="block mt-1 w-full">{{ old('information') }}</textarea>
                       </div>

                       <div class="md:flex justify-between">
                       <div class="mt-4">
                           <x-jet-label for="event" value="イベント日付" />
                           <x-jet-input id="event_date" class="block mt-1 w-full" type="text" name="event_date"  />
                       </div>
     
                       <div class="mt-4">
                           <x-jet-label for="start_time" value="開始時間" />
                           <x-jet-input id="start" class="block mt-1 w-full" type="text" name="start_time"  />
                       </div>
                       
                       <div class="mt-4">
                           <x-jet-label for="end_time" value="終了時間" />
                           <x-jet-input id="end_time" class="block mt-1 w-full" type="text" name="end_time"  />
                       </div>
                     </div>
                     <div class="md:flex justify-between items-end">
                       <div class="mt-4">
                          <x-jet-label for="max_people" value="定員数" />
                          <x-jet-input id="max_people" class="block mt-1 w-full" type="number" name="max_people" />
                       </div>
                       <div class="flex space-x-4 justify-around">
                          <input type="radio" name="is_visible" value="1" chacked />表示
                          <input type="radio" name="is_visible" value="0" />非表示
                       </div>
                       <x-jet-button class="ml-4">
                               新規登録
                       </x-jet-button>
                    </div>
                 </form>
               </div>
            </div>
        </div>
    </div>
    <script src="{{ mix('js/flatpickr.js')}}"></script>
</x-app-layout>

これでフォームリクエストバリデーションを使って、エラーを表示することが出来ました。
次はリスト表示ではなく、入力欄の上にバリデーションメッセージを表示させたいと思います。

実際の表示

すみません。
レイアウト崩れてますが、入力欄の上にバリデーションが表示されています。

image

実装方法

各入力欄の上に下記記述

@if($errors->has('event_name'))
    @foreach ($errors->get('event_name') as $message)
        <p style="color: red">{{  $message }}</p>
    @endforeach
@endif

$messageは、StoreEventRequestの、messages()の値を表示させています。

実際のblade

<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            イベント新規登録
        </h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
            <div class="max-w-2xl py-4 mx-auto">
            
                @if ($errors->any())
                    <p style="color: red">入力内容に誤りがあります</p>
                @endif
               
                 <form method="POST" action="{{ route('events.store') }}">
                     @csrf

                        @if($errors->has('event_name'))
                            @foreach ($errors->get('event_name') as $message)
                                <p style="color: red">{{  $message }}</p>
                            @endforeach
                        @endif
                        <div>
                           <x-jet-label for="event_name" value="イベント名" />
                           <x-jet-input id="event_name" class="block mt-1 w-full" type="text" name="event_name" :value="old('event_name')"  />
                        </div>

                        @if($errors->has('information'))
                            @foreach ($errors->get('information') as $message)
                                <p style="color: red">{{  $message }}</p>
                            @endforeach
                        @endif
                        <div class="mt-4">
                           <x-jet-label for="information" value="イベント詳細" />
                           <textarea row="3" id="information" name="information" class="block mt-1 w-full">{{ old('information') }}</textarea>
                        </div>

                        <div class="md:flex justify-between">

                            @if($errors->has('event_date'))
                                @foreach ($errors->get('event_date') as $message)
                                    <p style="color: red">{{  $message }}</p>
                                @endforeach
                            @endif
                            <div class="mt-4">
                                <x-jet-label for="event" value="イベント日付" />
                                <x-jet-input id="event_date" class="block mt-1 w-full" type="text" name="event_date"  />
                            </div>
                        
                            @if($errors->has('start_time'))
                                @foreach ($errors->get('start_time') as $message)
                                    <p style="color: red">{{  $message }}</p>
                                @endforeach
                            @endif
                            <div class="mt-4">
                                <x-jet-label for="start_time" value="開始時間" />
                                <x-jet-input id="start" class="block mt-1 w-full" type="text" name="start_time"  />
                            </div>

                            @if($errors->has('end_time'))
                                @foreach ($errors->get('end_time') as $message)
                                    <p style="color: red">{{  $message }}</p>
                                @endforeach
                            @endif
                            <div class="mt-4">
                               <x-jet-label for="end_time" value="終了時間" />
                               <x-jet-input id="end_time" class="block mt-1 w-full" type="text" name="end_time"  />
                            </div>
                        </div>

                        @if($errors->has('max_people'))
                            @foreach ($errors->get('max_people') as $message)
                                <p style="color: red">{{  $message }}</p>
                            @endforeach
                        @endif
                        <div class="md:flex justify-between items-end">
                        <div class="mt-4">
                           <x-jet-label for="max_people" value="定員数" />
                           <x-jet-input id="max_people" class="block mt-1 w-full" type="number" name="max_people" />
                        </div>

                       <div class="flex space-x-4 justify-around">
                          <input type="radio" name="is_visible" value="1" chacked />表示
                          <input type="radio" name="is_visible" value="0" />非表示
                       </div>
                       <x-jet-button class="ml-4">
                               新規登録
                       </x-jet-button>
                    </div>
                 </form>
               </div>
            </div>
        </div>
    </div>
    <script src="{{ mix('js/flatpickr.js')}}"></script>
</x-app-layout>

本日は以上となります。
最後まで見ていただきありがとうございました!

2
1
1

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
2
1