#03 Laravel基礎
FormRequestでバリデーションを整理する
コントローラー直書きの問題
「Laravel生活」シリーズでは、 バリデーション? フォームに入力されたデータが正しい形式かをチェックする処理。「メールアドレスの形式か」「空欄でないか」などを検証する。 をコントローラーに直接書きました。
// 📁 app/Http/Controllers/PostController.php
public function store(Request $request)
{
$request->validate([
'title' => 'required|max:100',
'body' => 'required',
'status' => 'required|in:draft,published',
]);
Post::create($request->only('title', 'body', 'status'));
return redirect()->route('posts.index');
}
ルールが少ないうちは問題ありません。しかし入力項目が多くなると、バリデーション部分がコントローラーを圧迫します。それを解決するのが フォームリクエスト? バリデーションルールを専用クラスにまとめる仕組み。コントローラーをすっきりさせるために使う。 です。
FormRequestを生成する
php artisan make:request StorePostRequest
app/Http/Requests/StorePostRequest.php が生成されます。
<?php
// 📁 app/Http/Requests/StorePostRequest.php(自動生成直後)
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StorePostRequest extends FormRequest
{
public function authorize(): bool
{
return false; // ← まずここを変更する
}
public function rules(): array
{
return [
//
];
}
}
authorize() と rules() を実装する
<?php
// 📁 app/Http/Requests/StorePostRequest.php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StorePostRequest extends FormRequest
{
// このリクエストを実行できるかの権限チェック
// とりあえず全員許可する場合は true を返す
public function authorize(): bool
{
return true;
}
// バリデーションルール
public function rules(): array
{
return [
'title' => ['required', 'max:100'],
'body' => ['required'],
'status' => ['required', 'in:draft,published'],
];
}
// エラーメッセージを日本語化する(任意)
public function messages(): array
{
return [
'title.required' => 'タイトルは必須です',
'title.max' => 'タイトルは100文字以内で入力してください',
'body.required' => '本文は必須です',
'status.required' => 'ステータスを選択してください',
'status.in' => 'ステータスの値が不正です',
];
}
}
コントローラーで使う
コントローラーの引数の型を Request から StorePostRequest に変えるだけです。
<?php
// 📁 app/Http/Controllers/PostController.php
namespace App\Http\Controllers;
use App\Http\Requests\StorePostRequest; // ← インポートを追加
use App\Models\Post;
class PostController extends Controller
{
public function store(StorePostRequest $request) // ← 型を変更
{
// バリデーションは FormRequest が自動で実行済み
// ここに来た時点でデータは検証済み
Post::create($request->only('title', 'body', 'status'));
return redirect()->route('posts.index')->with('success', '投稿を作成しました');
}
}
StorePostRequest を型宣言すると、Laravelが自動でバリデーションを実行します。失敗した場合は自動でフォームに戻り、エラーが $errors 変数に格納されます。
更新用の FormRequest も作る
作成と更新でルールが違う場合は別のクラスを作ります。
php artisan make:request UpdatePostRequest
<?php
// 📁 app/Http/Requests/UpdatePostRequest.php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdatePostRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'title' => ['required', 'max:100'],
'body' => ['required'],
'status' => ['required', 'in:draft,published'],
];
}
}
コントローラーの update メソッドにも適用します。
// 📁 app/Http/Controllers/PostController.php
public function update(UpdatePostRequest $request, Post $post) // ← 型を変更
{
$post->update($request->only('title', 'body', 'status'));
return redirect()->route('posts.show', $post)->with('success', '投稿を更新しました');
}
authorize() で認可を行う
authorize() は「このリクエストを実行する権限があるか」をチェックする場所です。ルートモデルバインディングと組み合わせると、「自分の投稿だけ編集できる」というチェックをここに書けます。
// 📁 app/Http/Requests/UpdatePostRequest.php
public function authorize(): bool
{
// ルートの {post} パラメーターからモデルを取得
$post = $this->route('post');
// 現在のログインユーザーが投稿の作者か確認
return $post->user_id === $this->user()->id;
}
authorize() が false を返すと403エラーになります。
まとめ
php artisan make:requestでFormRequestクラスを生成するrules()にバリデーションルールを書くmessages()でエラーメッセージを日本語化できるauthorize()で認可ロジックも書ける- コントローラーの型を変えるだけでバリデーションが自動実行される
次回は依存性注入とサービスコンテナを学びます。