FormRequestで入力値を補正を以前紹介しましたが、今度はちょっと違う補正の紹介です。何が違うというと、今度はバリデーションの後でなくバリデーション前に入力値を変えます。入力項目とDBに保存する項目の形態が違うときにとても便利です。とりあえず、それが必要なケースの説明から。

まず、DBに保存するのは、start_at(開始日時)とend_at(終了日時)の日時タイプ(mysqlならDATETIME)の2つ項目とします。しかし、両方の項目ともに日付は同じという仮定。いくつかのUIのバリエーションが考えられますが、私が考えたのは以下。

つまり、入力項目は、日付、開始時刻(数字)、終了時刻(数字)の3つの入力項目です。

日付はjquery-uiでカレンダーからの選択も可能(以下)であるし、時刻もドロップダウン、とすることもできますね。

画面から入ってくるのは、date, start_hr, end_hrの3つの値なのですが、さて、これらの入力値をバリデーションにかけて、DBには、start_atend_atの2つの項目に保存するには、どうしたらよいでしょうか?

そこで登場するのが、FormRequestです。

まず、以下のコマンドでFormRequestファイルを、app/Http/Requestsのディレクトリに作成します。

$ php artisan make:request EventRequest

作成されたファイルを以下のように編集します。


namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class EventRequest extends FormRequest
{
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'start_at'     => 'required|date|date_format:Y-m-d H:i:s',
            'end_at'       => 'required|date|date_format:Y-m-d H:i:s|after:start_at',
        ];
    }

    public function messages()
    {
        return [
            'date_format' => '不正な日時のフォーマットです',
        ];
    }

   public function attributes()
    {
        return [
            'start_at' => '開始日時',
            'end_at'   => '終了日時',
        ];
    }

    /**
     * Prepare the data for validation.
     *
     * @return void
     */
    protected function prepareForValidation()
    {
        // ここでDBに収納する項目を作成
        $this->merge([
            'start_at' => sprintf('%s %02d:00:00', $this->date, $this->start_hr),
            'end_at'   => sprintf('%s %02d:59:59', $this->date, $this->end_hr),
        ]);
    }
}

ここ、preparedForValidation()の関数において、入力値を、start_atend_atの入力値に変換しています。DBではそれらの項目はDateTimeのタイプなので、時間だけでなく分や秒も足すこと必要です。

コントローラのメソッドでは、以下のようにコールします。store()の引数が、通常のRequestでなくEventRequestとなっていることに注意を。


namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Http\Requests\EventRequest;

class EventController extends Controller
{
...
    /**
     * Store
     *
     * @param  \App\Http\Requests\EventRequest $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(EventRequest $request)
    {
        dd($request->all());
...

実行すると、dd()の出力は、

array:6 [▼
  "_token" => "npq1EPLTVvthufpgQiIpXIkxpwMPEsEEIBIzYf5A"
  "date" => "2020-10-08"
  "start_hr" => "8"
  "end_hr" => "17"
  "start_at" => "2020-10-08 08:00:00"
  "end_at" => "2020-10-08 17:59:59"
]

By khino