CakePHP 3 - 使用 LocalStringFormat 解析日期以更正 SQL 格式和正确验证

2021-12-21 00:00:00 validation php mysql cakephp

我们在 AppController 的 initialize 函数中声明了以下几行,以具有全局相同的日期显示格式:

//加载时的默认时间格式时间::$defaultLocale = 'de-DE';Time::setToStringFormat('dd.MM.YYYY');

这工作得很好.日期在视图中正确显示.但是,如果我们想保存带有日期字段的实体(提供的值无效),则会出现验证错误.验证器配置如下:

 $validator->add('datefield', 'valid', ['rule' => 'date'])->allowEmpty('datefield');

这是带有日期字段的实体的调试:

在 patchEntity 之前:

'datefield' =>'08.07.2014'

补丁实体之后:

'datefield' =>对象(蛋糕I18n时间){'时间' =>'2014-07-08T00:00:00+0000','时区' =>'世界标准时间','fixedNowTime' =>错误的},....'[错误]' =>['日期字段' =>['有效' =>'提供的值无效']],

有没有办法始终以正确的格式全局解析日期以保存实体和验证.

解决方案

解析(在编组过程中)和验证没有关系,前者会after后者发生.

检查 date 验证方法 API,它需要更多参数,即要使用的格式,以及要使用的自定义正则表达式,而不是预定义的.

<块引用>

date(string|DateTime $check, string|array $format 'ymd', string|null $regex null)

日期验证,确定传递的字符串是否为有效日期.钥匙期望完整的月、日和年将验证闰年.

年份从 1800 年到 2999 年有效.

格式:

  • dmy 27-12-2006 或 27-12-06 分隔符可以是空格、句点、破折号,正斜杠
  • mdy 12-27-2006 或 12-27-06 分隔符可以是空格、句点、破折号、正斜杠
  • ymd 2006-12-27 或 06-12-27分隔符可以是空格、句点、破折号、正斜杠
  • ...

[...]

API > CakeValidationValidation::date()

因此,为了正确验证本地化的德语数据,您必须指定 dmy 格式.

->add('datefield', 'valid', ['rule' => ['date', 'dmy']])

如果您想以一种可以从应用程序中的单个点更改格式的方式全局应用本地化验证,那么您可以例如使用自定义验证规则和全局可用的自定义提供程序来获取格式来自您的应用配置,例如

命名空间 AppValidation;使用 CakeCoreConfigure;使用 CakeValidationValidation;类 AppValidation{公共静态函数日期($check){返回 Validation::date($check, Configure::read('Locale.validation.dateFormat'));}}

$validator->provider('appValidation', 'AppValidationAppValidation');$validator->add('datefield', 'valid', ['规则' =>'日期','提供者' =>'应用验证'])

* 用于说明目的的未经测试的示例代码

另见食谱>验证> 自定义验证规则

we have declared the following lines in the initialize function of our AppController to have globally the same format for displaying dates:

    // default time formats on load
    Time::$defaultLocale = 'de-DE';
    Time::setToStringFormat('dd.MM.YYYY');

This worked fine. The date is displayed correcly in the view. But we get an validation error if we want to save the entity with the the date field (The provided value is invalid). The validator is configured like so:

    $validator
        ->add('datefield', 'valid', ['rule' => 'date'])
        ->allowEmpty('datefield');

Here a debug of the entity with the date field:

Before patchEntity:

'datefield' => '08.07.2014'

After patchEntity:

'datefield' => object(CakeI18nTime) {

        'time' => '2014-07-08T00:00:00+0000',
        'timezone' => 'UTC',
        'fixedNowTime' => false

    },
....
'[errors]' => [
        'datefield' => [
            'valid' => 'The provided value is invalid'
        ]
    ],

Is there a way to always parse the Date globally in the correct format for saving the entity and validation.

解决方案

Parsing (in the marshalling process) and validation have nothing to do with each other, the former will happen after the latter.

Check the date validation method API, it takes further arguments, that is, the format to use, and a custom regular expression to use instead of the predefined ones.

date(string|DateTime $check, string|array $format 'ymd', string|null $regex null)

Date validation, determines if the string passed is a valid date. keys that expect full month, day and year will validate leap years.

Years are valid from 1800 to 2999.

Formats:

  • dmy 27-12-2006 or 27-12-06 separators can be a space, period, dash, forward slash
  • mdy 12-27-2006 or 12-27-06 separators can be a space, period, dash, forward slash
  • ymd 2006-12-27 or 06-12-27 separators can be a space, period, dash, forward slash
  • ...

[...]

API > CakeValidationValidation::date()

So in order to properly validate your localized german data, you'll have to specify the dmy format.

->add('datefield', 'valid', ['rule' => ['date', 'dmy']])

If you want to apply localized validation globally, in a way where the format can be changed from a single point in your app, then you could for example use a custom validation rule and a globally available custom provider, which fetches the format from your apps configuration, like

namespace AppValidation;

use CakeCoreConfigure;
use CakeValidationValidation;

class AppValidation
{
    public static function date($check) {
        return Validation::date($check, Configure::read('Locale.validation.dateFormat'));
    }
}

$validator->provider('appValidation', 'AppValidationAppValidation');

$validator->add('datefield', 'valid', [
    'rule' => 'date',
    'provider' => 'appValidation'
])

* untested example code for illustration purposes

See also Cookbook > Validation > Custom Validation Rules

相关文章