完全な手順!Laravelバリデーション前にデータを加工する方法

さてさて、Laravelを使って開発を進めているとたまに、

データ送信した後でデータ加工してからバリデーションにかけたい!

なんてことがありませんか?

例えば、こんな場合です。

  1. 日付を入力
  2. 時間を入力
  3. この2つを合わせた日時が未来ならOK!

つまり、日付と時間を結合させてバリデーション・チェックしたいってことですね。

日付、もしくは時間だけでバリデーションしてしまうと、思ったとおりのことは実現できないと思います。

さぁ、ではこれを実現するにはどうすればいいでしょうか??
ひとつずつ見ていきましょう!

フォームを作る

まずはデータ送信するテストフォームを作ります。(もしすでにフォームがある方は次まで読み飛ばしてください)

冒頭の例でフォームを作るとこんな感じです。

HTML(Bladeテンプレート)はこうなります。

<form method="post" action="/date_time_post">
    @csrf
    <label>日付</label>
    <br>
    <input name="date" type="date">
    <br>
    <br>
    <label>時間</label>
    <br>
    <input name="time" type="time">
    <br>
    <br>
    <button type="submit">送信</button>
</form>

※ちなみに、inputのtypeに「date」とか「time」が使えるようになってきて便利になりましたね!

フォーム・リクエストを作る

では、このフォームからデータ送信したときに実行するバリデーションを作っていきましょう。バリデーションは「フォーム・リクエスト」の中に作成します。

Laravelではこのフォーム・リクエストをコマンド一発で作成することができます。以下のようにして実行してみてください。

php artisan make:request DateTimeRequest

これで、「/app/Http/Request/DateTimeRequest.php」が作成されました。

フォーム・リクエストをコントローラーに設置する

せっかくなので、日時バリデーションを作成する前に、このフォーム・リクエストをコントローラーへ設置しておきましょう。

こんな感じです。

use App\Http\Requests\DateTimeRequest;

class HomeController extends Controller
{
    public function date_time_post(DateTimeRequest $request) {

        echo 'バリデーションOK!';

    }

※Laravelではこのようにフォーム・リクエスト設置するだけで、もしバリデーションに失敗したら自動で元ページへリダイレクトしてくれて、さらにそのエラーメッセージまで取得することができます。さすがです!


バリデーションを作成する

ではここからが本題です。先ほどの「DateTimeRequest.php」を開いて中身を変更していきましょう。

まずは基本的な内容から。

例えば、

  • 日付が必須で、ちゃんとした日付のみOK!
  • 時間が必須で、ちゃんとした時間のみOK!

という条件でバリデーション・チェックしたい場合は以下のようになります。

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class DateTimeRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'date' => 'required|date',
            'time' => 'required|date_format:H:i'
        ];
    }
}

※authorize()はこの場合無条件でtrueを返しています。

バリデーションの前にデータ加工する方法

では、もし「date_time」という日付と時間を結合したデータをチェックしたい場合はどうすればいいでしょうか。

答えは、FormRequestから継承しているall()メソッドの上書きです。

// Overwrite
public function all($keys = null)
{
    return parent::all($keys);
}

※DateTimeRequest内に追加してください。

ただし、これだけでは今までと変わりがないので、以下のように日付と時間を結合して新たなデータを格納する必要があります。

// Overwrite
public function all($keys = null)
{
    $results = parent::all($keys);

    if($this->filled('date') && $this->filled('time')) {

        $results['date_time'] = $this->input('date') .' '. $this->input('time');

    }

    return $results;
}

これで、新しいデータ「date_time」に「日時」が格納されたことになります。

では、この日時にバリデーションを追加してみましょう。

public function rules()
{
    return [
        'date' => 'required|date',
        'time' => 'required|date_format:H:i',
        'date_time' => 'after:now'
    ];
}

バリデーションの意味は、「今より未来の日時だけOK!」です。施設の予約などを想定しています。

※詳しいバリデーションの中身については、全53種類!Laravel 5.6のバリデーション実例をご覧ください。

全ソースコード(コピペOK)

ということで今回利用したフォーム・リクエストが以下になります。
このコードを改造すれば色々と便利なバリデーションを実現することができると思いますので、ぜひ活用してくださいね。

※太字の部分が、あなたの環境に合わせて変更すべき場所です。

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class DateTimeRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'date' => 'required|date',
            'time' => 'required|date_format:H:i',
            'date_time' => 'after:now'
        ];
    }

    // Overwrite
    public function all($keys = null)
    {
        $results = parent::all($keys);;

        if($this->filled('date') && $this->filled('time')) {

            $results['date_time'] = $this->input('date') .' '. $this->input('time');

        }

        return $results;
    }
}

おわりに

ということで今回は、バリデーション前に送信データを加工し、さらにその加工データが正しいかどうかをチェックする手順をお届けしました。

Laravelって結構こういう「ちょっとレアなケース」にも対応できるように設計されているので、今回のようなパターンだけじゃなく色々と融通が効いて嬉しい限りです。

ぜひみなさんもご活用くださいね。

ではでは〜!



にほんブログ村 IT技術ブログへ  にほんブログ村 IT技術ブログ プログラム・プログラマーへ


BugGUI バグ報告を効率化
たった3分でバグ報告完了!? BugGUI