コントローラーのファイルが大きくなってきたな、と思ったら、FormRequestを使ってみようかと真剣に考え始めました。まずは、FormRequestとは何ものかの紹介からです。

FormRequestを使わないコントローラ

FormRequestを使わないコントローラというのは、例えば以下のコードに代表されます。

namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
 
class UserController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth'); //認証したユーザーのみがアクセス可能
    }
 
    public function edit()
    {
        $user = auth()->user(); // 認証したユーザーの情報を取得
 
        return view('user_edit')->with(compact('user'));
    }
 
    public function update(Request $request)
    {
       // リクエストのバリデーション
        $validated = $request->validate([
            'name'  => 'required',
            'email' => 'required|email',
        ]);
 
        // DBの情報を更新
        auth()->user()->update($validated);
 
        // ホーム画面へリダイレクト
        return redirect()->route('home');
    }
}

このコントローラを使用する、routeは以下のように定義されます。

routes/web.php
Route::get('/', function () {
    return view('welcome');
});
 
Auth::routes();
 
Route::get('/home', 'HomeController@index')->name('home');
 
Route::get('/user/edit', 'UserController@edit')->name('user.edit');
Route::put('/user/edit', 'UserController@update')->name('user.update');

よく見て欲しいのは、UserController::update()のメソッド。
リクエストの入力値をバリデートして、バリデーションをパスした入力値をそのまま、EloquestUserオブジェクト(auth()->user)のupdate()に渡して更新です。

ちなみに、このコントローラは、ログインしたユーザーが自分の情報を編集するためです。Laravelのデフォルトのプロジェクトにはユーザー認証のコードがついてきますが、この機能はありません。

FormRequestを使用したら

まず、コマンドラインから、FormRequestの作成です。

$ php artisan make:request UserRequest

これで、UserRequest.phpが作成されます。それを以下のように編集します。

app/Http/Requests/UserRequest.php
amespace App\Http\Requests;
 
use Illuminate\Foundation\Http\FormRequest;
 
class UserRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true; // すでにUserController::__construct()でチェックしてあるので、true
    }
 
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name'  => 'required',
            'email' => 'required|email',
        ];
    }
}

見ての通り、コントローラにあったバリデーションルールが移動されています。

コントローラの方は、

namespace App\Http\Controllers;
 
use App\Http\Requests\UserRequest; //ここで宣言
 
class UserController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }
 
    public function edit()
    {
        $user = auth()->user();
 
        return view('user_edit')->with(compact('user'));
    }
 
    public function update(UserRequest $request)
    {
        auth()->user()->update($request->validated()); // 1行になりました
 
        return redirect()->route('home');
    }
}

FormRequestを使うことでコントローラのコードの行数は減りました。しかし、FormRequestの定義のファイルが増えて全体のコードの行数は増えたことも事実。今回のような、簡単なコードではあまり得したことにはならない感じですね。ない方がわかりやすいとも思えます。しかし、もしバリデーションルールがもっとたくさんあったら、FormRequestはベターなのは明らかです。コードが複雑になったらリファクターして新規の関数を作成するのと同じかな。

しかし、FormRequestを使うことに関して他の利点はなんでしょう?次回からそれらの利点を探ってみます。

編集のブレード

参考として、作成したブレードファイルも掲載します。resources/views/auth/register.blade.phpをもとにしましたが、Eメールの入力において、type="email"のところ、type="text"にしています。バリデーションエラーの表示をテストしたかったためです。

resources/views/user_edit.blade.pohp
@extends('layouts.app')
 
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Register') }}</div>
 
                <div class="card-body">
                    <form method="POST" action="{{ route('user.edit') }}">
                        @csrf
                        @method('PUT')
 
                        <div class="form-group row">
                            <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Name') }}</label>
 
                            <div class="col-md-6">
                                <input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name', $user->name) }}" required autocomplete="name" autofocus>
 
                                @error('name')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>
 
                        <div class="form-group row">
                            <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
 
                            <div class="col-md-6">
                                <input id="email" type="text" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email', $user->email) }}" required autocomplete="email">
 
                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>
 
                        <div class="form-group row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Register') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
メルマガ購読の申し込みはこちらから。

By khino