3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Laravel]リクエスト値の整形にpassedValidationという選択肢

Posted at

やりたいこと

  • 例えば、WEBサイトの新規登録画面を作る状況で、郵便番号などを整形した上でDBへ登録したい時

  • Laravelを使うとなると、ベストプラクティスにもある通りフォームリクエストを使うことが多いと思うので、

    Viewから入力内容を含んだリクエストを送信

    フォームリクエストでバリデーション

    Contorollerでバリデーション済のリクエスト受け取り

    受け取ったリクエストに対して整形・・・★

みたいにやると思うが★の部分でControllerを汚すため、あまり望ましくないと思う

ということで今回のらやりたいことは「やりたいこと」は

「Controllerを汚さずにバリデーション済かつ、整形済みの値を取得する」

です。

手段

方法としては

  • 同じController内で整形用フォーム作る
  • 別階層に整形専用クラスを作成、使用

などいくつか方法はあるけど、自分の場合は

  • passedValidationメソッドを使う

という選択肢を使った次第

内容

  • passedValidationの説明は公式ドキュメントになくて、Githubから引用

使い方

  • フォームリクエストにpassedValidationメソッドを追加し、バリデーション後の処理を書くだけ。非常に簡単。
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class HogeRequest extends FormRequest
{
  ...
  ...
  // 郵便番号の整形(ハイフンが有ったらハイフン削除)
  public function passedValidation()
    {
        if (Str::contains($this->postal_code, '-')) {
            $formattedPostalCode = Str::remove('-', $this->postal_code);
            $this->merge([
                'postal_code' => $formattedPostalCode,
            ]);
        }
    }
}

注意点

  • 一個厄介なのが、フォームリクエストでControllerで整形後の内容は$requestには反映されるが、$request→validated()には反映されない点
    • リクエストの値がバリデーションを通っていることを明示的にするため、$request→validated()を使うことが多いと思うが、これでは整形前(=入力値そのまま)しか取得できない

↓HogeRequestでフォームリクエスト受け取り先Controller

class HogeController extends Controller
{
	public function register(HogeRequest $request)
	   {
				$validated = $request->validated();

				dd($validated); // 整形前(=ハイフン未削除)の値

				dd($request);  // 整形後(=ハイフン削除済)の値
		 }
}
  • なので、整形後の値を取得する方法は2つ
    • 1, $requestをそのまま使う
    • 2, 以下のように$validated = $request→validated()した後、$validatedの内容を$requestに置き換える
        $validated = $request->validated();
        // passedValidationで整形後の値で置き換え
        $validated['postal_code'] = $request->postal_code;

これはこれでビジネスロジック汚すので、別で専用メソッド作って呼び出すとかのがいいかもですね

    protected function ($request)
    {
        $validated = $request->validated();
        // passedValidationで整形後の値で置き換え
        $validated['postal_code'] = $request->postal_code;
				// 他に整形が必要なリクエスト値も置換え
				...
				...

        return $validated;
    }

尚、こことか

こことか

見ていると$requestに対してvalidated()を使うのは暗黙的なベストプラクティスに思われます。

補足

  • passedValidationの逆にバリデーション前にリクエスト処理を行えるメソッドとして、prepareForValidationがある
  • これもドキュメントには記載がないが、Githubを転記
    • いつ使うんだろう。。。

所見

  • ココまで書いて思うのは、自分のアサイン中のプロジェクトはvalidated()は基本必須なので、一番スマートなのは「別階層に整形専用クラスを作成、使用」かな、と思いました。。。
    • Controllerで専用クラスを呼び出して、1文で整形してしまうみたいな感じかな
      • 例えば、専用クラス名がViewHelperでメソッド名がformatPostalCodeであればこんな感じ
	public function register(HogeRequest $request)
    {
			// 郵便番号の整形
			ViewHelper::formatPostalCode($request->postalcode);
			...
    }

こっちのがControllerで余計な処理($vaidated$requestを再代入など)をしなくていいのでスッキリする。

しかも整形処理なんて、新規登録だけじゃなくて、登録情報変更でも使ったりする汎用性の高い処理なので、そっちのが望ましい

  • でも、プロジェクトとして$requestそのまま使うことを許容されているのであれば、断然こっちのが楽ですね

  • 公式ドキュメントに書いていない理由の個人的推測は、Laravelベンダーとしては

    $request→validated()推奨・・・★

    $request→validated()ではpassedValidationメソッドで処理後の値を取得できない」

    「★と相性悪いよね。。。」

ってとこでしょうね。

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

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?