章: 第4章: Laravelフレームワーク
コントローラのメソッドの半分以上がバリデーションコードになっていませんか?
$request->validate([...]) をコントローラに直書きし続けると、メソッドが肥大化して可読性もテスト性も下がります。フォームリクエストクラスに切り出すことで、バリデーションと認可のロジックを1ヶ所に集約できます。
コントローラにバリデーションを詰め込むと何が起きるか
同じバリデーションルールが複数のアクションにコピーされ、変更のたびに複数箇所を修正するリスクが生まれます。FormRequestクラスを使えば、ルールを1ヶ所で管理でき、コントローラはスッキリします。
FormRequestの良い例・悪い例
| 観点 | 悪い例 | 良い例 |
| バリデーション場所 | コントローラのメソッド内に直書き | FormRequest::rules() にまとめる |
| 認可 | コントローラ内で if ($user->cannot(...)) abort(403) |
FormRequest::authorize() に移す |
| エラーメッセージ | デフォルトのまま | messages() メソッドで日本語化 |
| 再利用 | ルールをコピーペースト | 複数アクションで同じFormRequestクラスを使う |
チェックポイント:
authorize()が常にtrueを返す実装は、アクセス制御を放棄しているサインです。認証済みユーザーのみ許可する場合はreturn $this->user() !== null;、さらに所有者確認が必要ならPolicyと組み合わせましょう。
コードサンプル
<?php
// php artisan make:request StorePostRequest
class StorePostRequest extends FormRequest {
public function authorize(): bool { return true; }
public function rules(): array {
return [
'title' => ['required', 'string', 'max:255'],
'body' => ['required', 'string'],
];
}
}
// コントローラはスッキリ
public function store(StorePostRequest $request): RedirectResponse {
Post::create($request->validated());
return redirect()->route('posts.index');
}
まとめ & 次のステップ
- フォームリクエストクラスでバリデーションと認可をコントローラから分離できます
validated()を使うことで許可したフィールドのみ取得でき、マスアサインメントが安全になりますmessages()メソッドでエラーメッセージを日本語化しましょうauthorize()を適切に実装し、権限のないリクエストを早期に拒否しましょう- テストでは
$this->actingAs($user)->post(...)で認可の動作確認を行いましょう
次回は ミドルウェア を学びます。HTTPリクエストの前後に共通処理を差し込む仕組みを整理しましょう。