【Laravel】フォームリクエスト:バリデーションと認可について
2023.10.14 /
本記事ではLaravelのフォームリクエスト(FormRequest)における、バリデーションと認可について詳しく解説していきます。
Webアプリケーションではフォーム入力などで登録されるデータの品質や整合性を確保することが重要です。必須項目が入力されていないデータや適切な形式でないデータを保存することは絶対に避けたいところです。
Laravelにはフォームリクエスト(FormRequest)という機能が備わっており、これを利用することでフォーム入力から送られたリクエストのバリデーションや認可を行うことができます。
本記事を通して、Laravelにおけるフォームリクエストについて理解を深めてください。ここで使用するLaravelのバージョンはLaravel10です。
フォームリクエスト(FormRequest)とは
Webアプリケーションにおいて、データの品質や整合性を確保するためにユーザーがフォーム入力したデータ(リクエスト)が適切か、必須項目が入力されているか等をチェックする必要があります。
例えばメールアドレスの形式が正しいか、年齢が数値であるか、パスワードが最小文字数を超えているか等を確認します。
このようなユーザーから送られたリクエストをチェックすることをバリデーションと呼びます。
Laravelにはリクエストをバリデーションするための方法としてFormRequestクラスが用意されています。
FormRequestはフォームから送信されたリクエストを操作、拡張するためのクラス
FormRequestは以下の機能を提供します。
- バリデーション(Validation)
- 認可(Authorization)
バリデーション(Validation)
FormRequestのメイン機能としてバリデーションが備わっています。バリデーション機能により、リクエストが適切であるか、必須項目の入力有無などを確認します。
またFormRequestを利用することでコントローラーのアクションメソッド内に記載していたバリデーションを異なる場所(FormRequest)に移動することができます。
FormRequestを使ってバリデーションをコントローラーから独立させることにより、再利用を可能にしてコードの可読性や保守性が上がります。
例えば次のようにコントローラーにバリデーションを書いていたとします。
public function store(Request $request)
{
$validationData = $request->validate([
'name' => 'required|max:255',
'email' => 'required|email|unique:users',
// その他ルールを記述
]);
// 保存処理を記述
}
これにFormRequestを利用すると次のようになります。
public function store(StoreRequest $request)
{
// 保存処理を記述
}
このようにFormRequestを利用することでコントローラー内のバリデーションを別の場所で管理できるようになります。
認可(Authorization)
FormRequestsではリクエストの認可も可能となっています。コントローラーのアクションを実行する前に、リクエストを行った特定のユーザーにアクションの実行が許可されているかどうかを判断します。
コントローラーに記載していたユーザーの認可ロジックも分離でき、読みやすいコードとなります。
FormRequestの作成方法
リクエストされたデータをバリデーションするためにFormRequestというクラスを作成します。
FormRequestは以下構文に沿ってArtisanコマンドで作成します。
php artisan make:request ファイル名
上記コマンドを実行するとapp/Http/Requests内にファイルが作成されます。ここではBook/CreateRequestを作成します。
php artisan make:request Book/CreateRequest
上記コマンドによりapp/Http/Requests/Book/CreateRequest.phpが作成されます。中を開くと次のようになっています。
<?php
namespace App\Http\Requests\Vessel;
use Illuminate\Foundation\Http\FormRequest;
class CreateRequest extends FormRequest
{
public function authorize(): bool
{
return false;
}
public function rules(): array
{
return [
//
];
}
}
ファイル内に作成されたCreateRequestクラスはFormRequestクラスを継承したクラスです。このクラスにはauthorizeメソッドとrulesメソッドを持っています。
authorizeメソッドはログイン中のユーザー情報からリスクエスの認証を判別します。つまりリクエストの認可を行います。初期値はfalseとなっており、全員のリクエストを許可する場合はtrueに変更します。
public function authorize(): bool
{
return true;
}
ログインしているかどうかでリクエストの許可をする場合、以下のようにAuthの認証機能を利用することもできます。
public function authorize()
{
if (Auth::check()) {
return true;
} else {
return false;
}
}
rulesメソッドはリクエストの値を検証する(バリデーション)ためのメソッドです。rulesメソッド内ではバリデーションルールを連想配列を返すように以下のように記述します。
public function rules(): array
{
return [
'title' => 'required | max:150',
'price' => 'numeric | min:1',
'author' => 'required',
];
}
連想配列にはキーにパラメーター、値にバリデーションルールを記載します。例えばtitleは必須(required)であり、150文字以内(max:150)であることをルールとしています。
パラメーター => ルール1 | ルール2 | …
バリデーションルールに使用できる属性は様々です。以下に属性の一部を記します。
属性 | 説明 |
---|---|
required | 入力必須 |
numeric | 数値である |
date | 日付フォーマットである |
boolean | 真偽値である |
array | 配列である |
その他の属性については以下サイトをご確認ください。
作成したFormRequestをコントローラーで利用するには、コントローラー側で読み込みやアクションメソッドに渡す必要があります。
// FormRequestの読み込み
use App\Http\Requests\TestRequest;
// フォームリクエストをアクションメソッドに渡す
public function index(TestRequest $request)
{
return view('index');
}
上記のようにアクションメソッドの引数にフォームリクエストを渡すことで、リクエストがバリデーションされます。
FormRequestの使用例:サンプルコード
FormRequestの使用例として、書籍情報を登録するWebアプリケーションを作成していきます。ここではすでにLaravelが利用できることを前提に解説していきます。
関連記事:【Laravel】Windowsにインストールして開発環境を構築する方法
またマイグレーションを実行してテーブルbooks(フィールド:title、author、price)は作成済み、モデルBookも作成していると想定します。
マイグレーションやモデルについては詳しくは以下記事をご参照ください
【Laravel】マイグレーションとは(migration):テーブル作成について
【Laravel】モデルとは:Modelの概要や作成方法について
View(blade)
ユーザーに表示されるView(blade)は以下のように記述します。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Book Register</title>
</head>
<body>
<h1>Book Register</h1>
<form action="{{ route('book.store') }}">
@csrf
<div>
<label for="title">書籍タイトル</label>
<input type="text" name="title" id="title">
</div>
<div>
<label for="author">作者</label>
<input type="text" name="author" id="author">
</div>
<div>
<label for="price">価格</label>
<input type="text" name="price" id="price">
</div>
<button type="submit">送信</button>
</form>
</body>
</html>
バリデーションエラーの表示
バリデーションでエラーが発生した場合は自動的に直前のURLにリダイレクトします。リダイレクト時はエラー情報とフォームに入力された値を付与しています。
バリデーションでエラーがあったときにエラー内容を画面出力したい場合は以下のようにコードを記述します。
@if ($errors->any())
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
バリデーション時に発生したエラーは$errorsに格納されます。上記では$errors->any()でエラーの有無を確認し、if判定でエラーがあった場合にエラーメッセージを画面に出力しています。
バリデーションでエラーがあると次のように表示されます。
バリデーションメッセージを日本語にする
初期設定ではバリデーションによるメッセージは英語になっています。バリデーションのエラーメッセージはlang/en/validation.phpで管理されていますが、Laravel10からはlangフォルダがありません。langフォルダを作成するには以下コマンドを実行します。
php artisan lang:publish
上記コマンドによりlang/en/validation/phpなどのファイルが作成されます。日本語のバリデーションメッセージを作成したいのでlang/ja/validation.phpを作成し、以下のようにコードを記述してください。
<?php
return [
'exists' => ':attribute は正しくありません',
'numeric' => ':attribute は数値で入力してください',
'required' => ':attribute は必須入力です',
'attributes' => [
'title' => 'タイトル',
'author' => '作者 ',
'price' => '価格 ',
],
];
次に言語の地域を日本に設定します。地域設定はconfig/app.phpのlocaleをjaに変更します。
'locale' => 'ja',
バリデーションエラー時に入力データがクリアされる
バリデーションエラーが発生すると、フォームに入力していたデータはすべてクリアされてしまいます。これではユーザーが再度フォーム入力を行う必要があるため、このままではよろしくないです。
Laravelに備わっているoldヘルパーを使用することでバリデーションエラーが発生しても入力内容が消えないようにできます。oldヘルパーは以下のようにvalue属性に使用します。
old('キー名')
<input type="text" name="title" id="title" value="{{ old('title') }}">
oldヘルパーはセッションに保管されている入力内容を取り出し、もし値が取得できなければ空を返します。
web.php
ルーティングは次のように記述します。
Route::post('/book/store', \App\Http\Controllers\Book \StoreController::class)
->name('book.store');
FormRequests
FormRequestsはまず以下コマンドを実行してCreateRequestファイルを作成します。
php artisan make:request Book/CreateRequest
次に中身は以下のように記述します。
use Illuminate\Foundation\Http\FormRequest;
class CreateRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'title' => 'required',
'author' => 'required',
'price' => 'numeric | nullable',
];
}
}
Controller
以下コマンドを実行してコントローラーを作成します。ここではシングルアクションコントローラを作成しています。
php artisan make:controller Book/StoreController --invokable
次に作成したコントローラーには次のように記述します。
<?php
namespace App\Http\Controllers\Vessel;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Book;
use App\Http\Requests\Book\CreateRequest;
class StoreController extends Controller
{
public function __invoke(CreateRequest $request)
{
$vessel = new Book();
$vessel->title = $request->title;
$vessel->author = $request->author;
$vessel->price = $request->price;
$vessel->save();
return view('book.index');
}
}
上記のコントローラーにより、リクエストのバリデーションが行われ、問題なければテーブルにフォーム入力したデータが登録されます。