LoginSignup
0
0

More than 3 years have passed since last update.

Laravel Validator 複数の日付フォーマットに対応したい場合

Posted at

やりたいこと

Laravelのバリデーションで複数のフォーマットを許可するバリデーションを書きたい。

具体的には
- 2018/01/01 (Y/m/d)
- 2018/1/01 (Y/n/d)
- 2018/01/1 (Y/m/j)
- 2018/1/1 (Y/n/j)

のどれかでだったらOKというバリデーションが書きたかった。

※そもそもなんでそんな状況になる? というのは触れずに。。。

前提

Laravel 5.5
PHP 7.2

解決方法

複数記載できるバリデータを作成した。
フォーマットのチエック処理は本家に合わせた
本家 date_formatバリデータの実装

app/Rules/DateFormats.php
<?php

namespace App\Rules;

use DateTime;
use Illuminate\Contracts\Validation\Rule;

class DateFormats implements Rule
{
    protected $dateFormats = [];

    /**
     * Create a new rule instance.
     *
     * @return void
     */
    public function __construct(array $dateFormats)
    {
        $this->dateFormats = $dateFormats;
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        foreach ($this->dateFormats as $key => $format) {
            if (! is_string($value) && ! is_numeric($value)) {
                return false;
            }

            $date = DateTime::createFromFormat('!'.$format, $value);
            $isValidated = $date && $date->format($format) == $value;

            if($isValidated)
            {
                //バリデーションが成功した時点で true 返却
                return true;
            }
        }

        return false;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return ':attribute に正しい日付を入力してください';
    }
}

使い方

○○FormRequest
public function rules()
{
    return [
        'inputDate' => [
            'required',
            new App\Rules\DateFormats(['Y/m/d', 'Y/n/d', 'Y/m/j', 'Y/n/j'])
        ]
    ];
}

テストコード

tests/Unit/Rules/DateFormatsTest.php
<?php

namespace Tests\Unit\App\Rules;

use Validator;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

use App\Rules\DateFormats;

class DateFormatsTest extends TestCase
{


    protected $dateFormats = ['Y/m/d', 'Y/n/d', 'Y/m/j', 'Y/n/j'];

    /**
     *
     * @return void
     */
    public function test_date_formats()
    {   
        $testInput = [
            '2018/01/01' => false,
            '2018/01/1' => false,
            '2018/1/01' => false,
            '2018/1/1' => false,
            '12:00' => true,
            '23:00' => true,
        ];

        foreach ($testInput as $dateValue => $expected) {

            $input['inputDate'] = $dateValue;
            $validator = Validator::make($input, [
                'inputDate' => [
                    new DateFormats($this->dateFormats)
                ]
            ]);
            $this->assertEquals( $validator->fails() ,$expected);
        }
    }
}

# ./vendor/bin/phpunit ./tests/Unit/Rules/DateFormatsTest.php
PHPUnit 6.5.7 by Sebastian Bergmann and contributors.

Error:         No code coverage driver is available

.                                                                   1 / 1 (100%)

Time: 805 ms, Memory: 12.00MB
0
0
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
0
0