LoginSignup
3
4

More than 5 years have passed since last update.

Laravel5.2で存在する"年月”のvalidateしてみた

Last updated at Posted at 2016-09-13

Laravel5.2で、正しい年月か?をvalidateしようとして理不尽なことになったのでメモ。

やりたいこと

Laravel5.2で、年月のフォーマットだけでなく、存在する年月かをValidateする。

いきさつ

Laravel5.2の使用可能なバリデーションルールによると、「日付」「日付形式」の2パターンが利用出来る。

が。ですよ。

ExampleController.php
$validator = Validator::make($input, [
    'from' => 'bail|required|date_format:Ym|before:"now"',
    'to' => 'bail|required|date_format:Ym|before:"now"|after:from',
]);
if ($validator->fails()) {
    throw new MyValidatorException();
}

のように日付形式をチェックするよう書いてやって、

from=201514
to=201520
とパラメータを渡してテストしてもエラーにならない!?

中を見てみる

Illuminate\Validation\Validator.php

    /**
     * Validate that an attribute matches a date format.
     *
     * @param  string  $attribute
     * @param  mixed   $value
     * @param  array   $parameters
     * @return bool
     */
    protected function validateDateFormat($attribute, $value, $parameters)
    {
        $this->requireParameterCount(1, $parameters, 'date_format');

        if (! is_string($value) && ! is_numeric($value)) {
            return false;
        }

        $parsed = date_parse_from_format($parameters[0], $value);

        return $parsed['error_count'] === 0 && $parsed['warning_count'] === 0;
    }

のように、「指定された日付フォーマット」として分割できるか?だけチェックして、それぞれの正当性をチェックしてくれない。
さっきの、"201520"を渡してデバッグすると、
スクリーンショット 2016-09-13 17.01.28.png
っていうありさまである。
month=20が存在するかはチェックされない。

参考までに、「日付」の場合こんなことをしている。

Illuminate\Validation\Validator.php
 /**
     * Validate that an attribute is a valid date.
     *
     * @param  string  $attribute
     * @param  mixed   $value
     * @return bool
     */
    protected function validateDate($attribute, $value)
    {
        if ($value instanceof DateTime) {
            return true;
        }

        if ((! is_string($value) && ! is_numeric($value)) || strtotime($value) === false) {
            return false;
        }

        $date = date_parse($value);

        return checkdate($date['month'], $date['day'], $date['year']);
    }

カスタムバリデーションの作成

Validatorクラスを自作します。
※requireParameterCount()はIlluminate\Validation\Validator.phpから引っ張ってきただけなので消してもオK。

Validator.php
<?php

namespace Myapp\Services\Validator;


class Validator {

    /**
     * Validate that an attribute is a valid year month.
     *
     * @param  string  $attribute
     * @param  string $parameters 日付パラメータ
     * @param  mixed  $value 検証値
     * @return bool
     */
    public function validateYearMonth($attribute, $value, $parameters)
    {
        $this->requireParameterCount(1, $parameters, 'date_ym');

        if (! is_string($value) && ! is_numeric($value)) {
            return false;
        }

        $parsed = date_parse_from_format($parameters[0], $value);

        return checkdate($parsed['month'], 1, $parsed['year']);
    }


    protected function requireParameterCount($count, $parameters, $rule)
    {
        if (count($parameters) < $count) {
            throw new InvalidArgumentException("Validation rule $rule requires at least $count parameters.");
        }
    }
}

アプリに登録します。

AppServiceProvider.php
<?php

namespace Myapp\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        \Validator::extend(
            'date_ym', 'Myapp\Services\Validator\Validator@validateYearMonth'
        );
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
    }
}

Controllerで検証内容を定義します。

ExampleController.php
$validator = Validator::make($input, [
    'from' => 'bail|required|date_ym:Ym|before:"now"',
    'to' => 'bail|required|date_ym:Ym|before:"now"|after:from',
]);
if ($validator->fails()) {
    throw new MyValidatorException();
}

以上で、意図した通り、パラメータに"201520"のような不正な年月が指定されてもエラーになりました。

とりあえずここまで。

追記)
ちなみに、before:"now"が期待通りに行きませんね。。。。

参考

https://readouble.com/laravel/5.2/ja/validation.html#available-validation-rules
https://readouble.com/laravel/5.2/ja/validation.html#custom-validation-rules
https://blog.e2info.co.jp/2016/06/05/laravel_custom_validation/

3
4
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
3
4