コントローラーのファイルが大きくなってきたな、と思ったら、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は以下のように定義されます。
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()のメソッド。
リクエストの入力値をバリデートして、バリデーションをパスした入力値をそのまま、EloquestのUserオブジェクト(auth()->user)のupdate()に渡して更新です。
ちなみに、このコントローラは、ログインしたユーザーが自分の情報を編集するためです。Laravelのデフォルトのプロジェクトにはユーザー認証のコードがついてきますが、この機能はありません。
FormRequestを使用したら
まず、コマンドラインから、FormRequestの作成です。
$ php artisan make:request UserRequest
これで、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"にしています。バリデーションエラーの表示をテストしたかったためです。
@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
メルマガ購読の申し込みはこちらから。
