【Laravel】FormRequestでバリデーションを実装する方法

当ページのリンクには広告が含まれています。
いずみ

こんな悩みを解決できる記事を書きました!

僕は現役フリーランスエンジニア(歴年)で、資格は個保有しています。

Laravelのコントローラーにバリデーションをベタ書きしていて読みにくい」と感じていませんか?

コントローラーのstoreメソッドやupdateメソッドに$request->validate() を並べていくと、処理が縦に長くなって見通しが悪くなります。

FormRequestを使えば、バリデーションのルールとエラーメッセージをコントローラーの外へ切り出せます

いずみ

フォームリクエストはフォーム画面でもAPIでも使う基本機能なので、丁寧に解説します。

ということで、本記事ではLaravelのFormRequestでバリデーションを実装する方法を解説します。

いずみ

すぐ読み終わるので、ぜひ最後まで読んでくださいませ。

スクロールできます
【当サイト】おすすめフリーランスエージェント3選
エージェント評価ポイント公式サイト
レバテックフリーランス

5.0
業界最大級のエージェント。
高単価案件が豊富。
公式
Midworks

4.8
満足度調査で
3年連続3冠を達成。
公式
ITプロパートナーズ

4.6
週2〜3向けの案件が豊富。公式
執筆者/監修者
  • フリーランスエンジニア(保有資格個、企業と直接契約
  • ブログ・アフィリエイト歴7年(2018年〜)
  • ブランドせどりで月利50万円⇨脱サラ
  • 投資(仮想通貨・FX)歴7年(2018年〜)
  • X(旧Twitter)フォロワー約1,900人
  • 運営者情報はこちら
いずみです
目次

【Laravel】FormRequestでバリデーションを実装する方法

早速ですが、LaravelのFormRequestでバリデーションを実装する手順を見ていきます。

FormRequestとは何か

FormRequestは、1つのリクエストに対するバリデーションと認可のロジックをまとめる専用クラスです。

コントローラーのメソッド引数にFormRequestクラスを型指定すると、コントローラーの処理が動く前にバリデーションが自動で実行されます。

検証に失敗した場合は、フォーム画面なら自動でリダイレクトとエラー表示、JSONを期待するリクエストなら422のレスポンスが返ります。

いずみ

コントローラーは「検証済みの値を受け取って処理するだけ」の状態になります。

FormRequestクラスを作成する

まずはartisanコマンドでFormRequestクラスを作成します。

STEP
artisanコマンドでクラスを生成する

ターミナルでmake:requestコマンドを実行します。

php artisan make:request StorePostRequest

app/Http/Requests/StorePostRequest.php が生成されます。

STEP
authorizeメソッドで実行可否を決める

authorizeメソッドがtrueを返すと、リクエストの実行が許可されます。

ログインユーザー全員に許可したい場合はtrueを返すだけで問題ありません。

falseを返すと403エラーになり、コントローラーの処理は実行されません。

STEP
rulesメソッドにルールを書く

rulesメソッドが返す配列に、フィールドごとのバリデーションルールを定義します。

いずみ

次のコードで具体的な中身を見ていきます。

rulesメソッドにバリデーションルールを定義する

生成されたクラスを編集し、authorize・rules・messages・attributesの4つのメソッドを整えます。

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StorePostRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'title' => ['required', 'string', 'max:255'],
            'body' => ['required', 'string'],
            'status' => ['required', 'in:draft,published'],
            'published_at' => ['nullable', 'date'],
        ];
    }

    public function messages(): array
    {
        return [
            'title.required' => 'タイトルは必須です。',
            'title.max' => 'タイトルは255文字以内で入力してください。',
            'status.in' => 'ステータスの値が不正です。',
        ];
    }

    public function attributes(): array
    {
        return [
            'title' => 'タイトル',
            'body' => '本文',
        ];
    }
}

rulesメソッドでは、ルールをパイプ区切りの文字列('required|string')ではなく配列で書く方が、条件が増えたときに読みやすくなります。

messagesメソッドで「ルールごとのエラーメッセージ」、attributesメソッドで「項目名の表示」を上書きできます。

コントローラーでフォームリクエストを受け取る

コントローラーのメソッド引数に、作成したStorePostRequestを型指定します。

<?php

namespace App\Http\Controllers;

use App\Http\Requests\StorePostRequest;
use App\Models\Post;

class PostController extends Controller
{
    public function store(StorePostRequest $request)
    {
        $validated = $request->validated();

        $post = Post::create($validated);

        return redirect()->route('posts.show', $post);
    }
}

storeメソッドの中に入った時点で、すでにバリデーションは通過済みです。

$request->validated() は、rulesメソッドに定義したキーだけを含む配列を返します。

一部の項目だけ欲しいときは$request->safe()->only(['title', 'body']) のように絞り込めます。

いずみ

フォームから送られた余計なパラメータがPost::create() に混ざらないので、Mass Assignment対策にもなります。

エラーメッセージと項目名を日本語にする

messagesメソッドは「フィールド名.ルール名」をキーにして、個別のメッセージを差し替えます。

全ルール共通の文言(「〜は必須です」など)を日本語化したい場合は、lang/ja/validation.php を用意する方法もあります。

attributesメソッドで項目名を日本語にしておくと、共通文言の:attribute 部分が「タイトル」「本文」に置き換わります。

prepareForValidationで入力値を整形する

バリデーション前に値を加工したいときは、prepareForValidationメソッドを使います。

<?php

use Illuminate\Support\Str;

// StorePostRequest クラス内に追記する
protected function prepareForValidation(): void
{
    $this->merge([
        'slug' => Str::slug((string) $this->input('title')),
        'title' => trim((string) $this->input('title')),
    ]);
}

mergeメソッドでリクエストに値を差し込むと、加工後の値がrulesメソッドの検証対象になります。

前後の空白除去やslugの自動生成など、コントローラーに書きがちな下処理をFormRequest側へ寄せられます。

いずみ

整形とバリデーションが1つのクラスに集まるので、入力の仕様を追いやすくなります。

afterメソッドで項目をまたいだ検証をする

「statusがpublishedのときだけpublished_atが必須」のような、複数フィールドにまたがる検証はrulesの配列だけでは書きにくくなります。

Laravel 11以降で追加されたafterメソッドを使うと、追加の検証をクロージャで書けます。

<?php

use Illuminate\Validation\Validator;

// StorePostRequest クラス内に追記する
public function after(): array
{
    return [
        function (Validator $validator) {
            if ($this->input('status') === 'published'
                && ! $this->input('published_at')) {
                $validator->errors()->add(
                    'published_at',
                    '公開する場合は公開日時を入力してください。'
                );
            }
        },
    ];
}

afterメソッドはクロージャの配列を返し、rulesの検証が終わったあとに順番に実行されます。

古いバージョンではwithValidatorメソッドで同じことができるので、環境に合わせて選びます。

APIでバリデーションエラーをJSONで返す

リクエストのAcceptヘッダーがJSONを示している場合、FormRequestは自動で422のJSONレスポンスを返します。

レスポンスの形を自分で決めたいときは、failedValidationメソッドを上書きします。

<?php

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;

// StorePostRequest クラス内に追記する
protected function failedValidation(Validator $validator): void
{
    throw new HttpResponseException(response()->json([
        'message' => '入力内容にエラーがあります。',
        'errors' => $validator->errors(),
    ], 422));
}

APIとフォーム画面で同じFormRequestを使い回す場合は、$this->expectsJson() で分岐させる書き方も選べます。

いずみ

フロント側は「errorsキーにフィールド名ごとの配列が入る」と決めておくと扱いやすいです。

スクロールできます
【当サイト】おすすめフリーランスエージェント3選
エージェント評価ポイント公式サイト
レバテックフリーランス

5.0
業界最大級のエージェント。
高単価案件が豊富。
公式
Midworks

4.8
満足度調査で
3年連続3冠を達成。
公式
ITプロパートナーズ

4.6
週2〜3向けの案件が豊富。公式

【厳選】フリーランスエンジニアにおすすめなエージェント3選

フリーランスエンジニアになるにはエージェントから案件をもらう必要があります。

僕が実際に利用しているおすすめエージェントを紹介しますね。

いずみ

エージェントは必ず複数登録してください。

担当者によっては「全然案件紹介してくれない…」みたいなこともあるので…

僕は実際に5つのエージェントを使い回していますよ。

フリーランスを始めるなら「

案件数マージン率単価
約88,000件非公開
初心者福利厚生申し込み
無料
Good Point
  • 業界最大級の案件数。
  • 業界トップクラスの高単価報酬、低マージン(平均年収862万円)。
  • 案件参画中のフォローの充実。

※詳細は「【業界最大手】レバテックフリーランスとは?メリットや利用手順を解説!」を参照。

は業界最大手のフリーランスエージェントです。

とにかく案件数が多いので、とりあえず登録しておけば間違いないエージェントです!

いずみ

僕もはじめてフリーランスの案件を貰ったのはです。

保有している案件数が多いので、業務経験がなくても何かしらの案件は紹介してもらえますよ(僕はJavaの経験3年でも案件を貰えました)。

手厚い保障を重視したいなら「

案件数マージン率単価
約10,000件非公開
初心者福利厚生申し込み
無料
Good Point
  • 手厚い保障で正社員並みの安心感。
  • 還元率60%超え&単価公開でクリアな契約。
  • 給与保障制度(審査あり)。

は手厚い保障が特徴のフリーランスエージェントです。

フリーランスを目指しているけど不安な方や保障を重視したい方におすすめです。

いずみ

僕も何度か案件を紹介してもらいました。

自分のスキルに合った案件を紹介してもらえましたし、電話のやり取りも非常に丁寧でした。

週2〜3日の案件探しなら「

案件数マージン率単価
約5,000件非公開
初心者福利厚生申し込み
経験者向け無料
Good Point
  • IT案件に特化したフリーランスエージェント。
  • 週2〜3日の案件が豊富。
  • リモート案件が多く、直エンドなので単価も高い。

※詳細は「【週2・3案件】ITプロパートナーズとは?メリットや利用手順を解説!」を参照。

はIT案件に特化したフリーランスエージェントです。

週2〜3日から参画できる案件が豊富なので、起業したい人にもおすすめです。

いずみ

週2〜3日の案件はある程度スキルがないと紹介してもらえない印象です。

とはいえ、週5の案件ももちろんありますし、僕が利用した時は迅速・丁寧に対応していただきました!

よくある質問

authorizeメソッドはtrueを返すだけでよいですか?

権限チェックが不要ならtrueで問題ありません。

投稿の所有者だけ更新を許可したい場合などは、authorizeメソッドの中でGateやPolicyを呼び、真偽値を返します。

検証済みのデータだけを受け取るにはどうしますか?

$request->validated() でrulesに定義したキーだけの配列を取得できます。

一部だけ欲しいときは$request->safe()->only([...])except([...]) を使います。

フォームリクエストをテストできますか?

機能テストでエンドポイントにリクエストを送り、assertInvalid()assertValid() で結果を検証するのが手軽です。

rulesメソッド単体の確認なら、クラスをインスタンス化してrulesの戻り値を配列として比較する方法もあります。

まとめ

今回は、LaravelのFormRequestでバリデーションを実装する方法について解説しました。

以下が本記事のまとめになります。

まとめ
  • FormRequestはmake:requestで生成し、rulesメソッドにルールを配列で書く。
  • コントローラーの引数に型指定すると自動で検証が走り、validated()で検証済みデータを取得できる。
  • messagesとattributesで日本語化、prepareForValidationで前処理、afterメソッドで項目をまたいだ検証ができる。
  • JSONを期待するリクエストには自動で422を返し、failedValidationで形を調整できる。
まとめ
  • おすすめ本
¥2,673 (2023/07/23 15:53時点 | Amazon調べ)

Laravelの勉強なら「」が分かりやすくておすすめですよ♪

いずみ

最後までお読みいただき、ありがとうございました!

スクロールできます
【当サイト】おすすめフリーランスエージェント3選
エージェント評価ポイント公式サイト
レバテックフリーランス

5.0
業界最大級のエージェント。
高単価案件が豊富。
公式
Midworks

4.8
満足度調査で
3年連続3冠を達成。
公式
ITプロパートナーズ

4.6
週2〜3向けの案件が豊富。公式
  • クソおすすめ本
¥4,480 (2024/06/01 23:28時点 | Amazon調べ)
いずみ

海外のエンジニアがどういった思考で働いているかが理解できます。

海外に行く気はないけど海外エンジニアの動向が気になる雑魚エンジニアにおすすめです(本当におすすめな本しか紹介しないのでご安心を)。

この記事が気に入ったら
フォローしてね!

シェアしてね!
  • URLをコピーしました!
目次