やりたいこと
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