FormRequestのバリデーションを問題なくパスしたら、コントローラで$request->validatedで配列としてフォームの入力値を取得できます。取得後の値は安全なのでそのままDBに保存することも可能です。しかし、その配列から必要のない値を抜いたり、足りない値を追加したりとかの処理はどうするかという説明です。

会員登録のFormRequest

例として会員登録の画面を使います。画面はこんな感じです。

その画面の入力をチェックするFormRequestは以下と定義します。

namespace App\Http\Requests;

use App\Rules\CaptchaRule;
use App\Rules\CustomerPasswordRule;
use Illuminate\Foundation\Http\FormRequest;

class CustomerRequest extends FormRequest
{
    public function rules()
    {
        $rules = [
            'email'                => ['required', 'email', 'unique:customer,email'],
            'password'             => ['required', new CustomerPasswordRule, 'confirmed'],
            'name'                 => ['required'],
            'g-recaptcha-response' => ['required', new CaptchaRule],
        ];

        return $rules;
    }
}

CustomerPasswordRuleCaptchaRuleは事前に用意したカスタムのバリデーションのクラスです。

CustomerRequestのバリデーションを問題なく通過したら、以下のようにコントローラでDBに保存します。


namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use App\Http\Requests\CustomerRequest;
use App\Models\Customer;
use Illuminate\Foundation\Auth\RegistersUsers;

class RegisterController extends Controller
{
    use RegistersUsers;

...
    /**
     * 会員の登録
     *
     * @param  \App\Http\Requests\CustomerRequest  $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function register(CustomerRequest $request)
    {
        $validated = $request->validated();

        Customer::create($validated);
        ...
    }
}

ここでのregister()メソッドの$validatedの値の中身を見てみましょう。

$validated = [
  "email" => "test@example.com",
  "password" => "Test1234567890!",
  "name" => "テスト太郎",
  "g-recaptcha-response" => "03AGdBq26f1ycQWiqz2OeBFz....",
]

DBに保存するのに必要なのは、email, password(暗号化する)、nameの3つだけで、キャプチャのg-recaptach-responseは必要でありませんので、先の配列値から抜く必要あります。また、会員が有効かどうかを指定するactive_flagが必要なので、その値を配列に加える必要あります。

このような処理を行うには、Laravelのバージョン8.x以降では、以下のようにvalidated()を使わずに、safe(), merge(), except()を使って可能です。

...
    $input = $request->safe()
        ->merge(['active_flag' => 'Y'])
        ->except(['g-recaptcha-response']);

    Customer::create($input);
...

safeは、バリデーションをパスした値を抽出し、mergeは値を追加、exceptは値を削除です。しかし、mergeとexceptの使用の順番には注意してください。これらを逆にするとエラーとなってしまいます。なぜなら、exceptは配列を返すのでその後にメソッドの連結ができません。

処理の結果の配列は、以下のようになります。

$input = [
  "email" => "test@example.com",
  "password" => "Test1234567890!",
  "name" => "テスト太郎",
  "active_flag" => "Y",
]

よりフレキシブルな処理を望むなら、以下のようにcollect()を通してCollectionのオブジェクトにすることです。

...
    $input = $request->safe()
        ->collect()
        ->except(['g-recaptcha-response'])
        ->merge(['active_flag' => 'Y'])
        ->all();

    Customer::create($input);
...

さて、safe()の対応がないLaravel 7.xではどう対応しましょう。
こちらも、配列をCollectionにしてしまえば、問題ありません。

...
    $input = collect($request->validated())
        ->except(['g-recaptcha-response'])
        ->merge(['active_flag' => 'Y']
        ->all();

    Customer::create($input);
...

私としては、Collectionを使用した方が好きです。
以下のように、ケースにより配列の中身を変えることも簡単です。

       $input = collect($request->validated())
            ->when(! $request->active_flag, function ($collection) {
                return $collection->put('active_flag', 'N'); // 値がないときはNとする
            })
            ->when(! $request->paymethod_id, function ($collection) {
                $collection->forget([ // 値がないときは、以下の設定は必要ではない
                    'paymethod_id',
                    'card_number',
                    'card_exp',
                    'card_holder',
                ]);

                return $collection;
            })
            ->all();

By khino