【问题标题】:CakePHP 3 DateTime Validation Iso 8601 with timezoneCakePHP 3 DateTime Validation Iso 8601 with timezone
【发布时间】:2017-02-06 12:24:27
【问题描述】:

我正在尝试在 cakePHP 3 (3.3.13) 中验证日期。我收到的数据是带有时区的 ISO 8601 格式,例如 2017-02-17T23:00:00.000Z 。

我有一个简单的$validator->date() 规则,它总是无法验证日期。我尝试使用我自己的验证提供程序,在其中我根据提供的值构建了一个 Chronos 对象。由于 Chronos 使用 DateTimeInterface 验证成功,但我收到 SQL 错误:

SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: '2017-02-17T23:00:00.000Z' for column 'launchdate' at row 1

这是我的 bootstrap.php:

require __DIR__ . '/paths.php';
require ROOT . DS . 'vendor' . DS . 'autoload.php';
require CORE_PATH . 'config' . DS . 'bootstrap.php';

use Cake\Cache\Cache;
use Cake\Console\ConsoleErrorHandler;
use Cake\Core\App;
use Cake\Core\Configure;
use Cake\Core\Configure\Engine\PhpConfig;
use Cake\Core\Plugin;
use Cake\Datasource\ConnectionManager;
use Cake\Error\ErrorHandler;
use Cake\Log\Log;
use Cake\Network\Email\Email;
use Cake\Network\Request;
use Cake\Routing\DispatcherFactory;
use Cake\Utility\Inflector;
use Cake\Utility\Security;

try {
    Configure::config('default', new PhpConfig());
    Configure::load('app', 'default', false);
} catch (\Exception $e) {
    die($e->getMessage() . "\n");
}
if (!Configure::read('debug')) {
    Configure::write('Cache._cake_model_.duration', '+1 years');
    Configure::write('Cache._cake_core_.duration', '+1 years');
}
date_default_timezone_set('UTC');
mb_internal_encoding(Configure::read('App.encoding'));
ini_set('intl.default_locale', 'en_US');
$isCli = php_sapi_name() === 'cli';
if ($isCli) {
    (new ConsoleErrorHandler(Configure::consume('Error')))->register();
} else {
    (new ErrorHandler(Configure::consume('Error')))->register();
}
if ($isCli) {
    require __DIR__ . '/bootstrap_cli.php';
}
if (!Configure::read('App.fullBaseUrl')) {
    $s = null;
    if (env('HTTPS')) {
        $s = 's';
    }
    $httpHost = env('HTTP_HOST');
    if (isset($httpHost)) {
        Configure::write('App.fullBaseUrl', 'http' . $s . '://' .      $httpHost);
    }
    unset($httpHost, $s);
}
Cache::config(Configure::consume('Cache'));
ConnectionManager::config(Configure::consume('Datasources'));
Email::configTransport(Configure::consume('EmailTransport'));
Email::config(Configure::consume('Email'));
Log::config(Configure::consume('Log'));
Security::salt(Configure::consume('Security.salt'));
Log::config('default', [
    'engine' => 'Syslog'
]);
Request::addDetector('mobile', function ($request) {
    $detector = new \Detection\MobileDetect();
    return $detector->isMobile();
});
Request::addDetector('tablet', function ($request) {
    $detector = new \Detection\MobileDetect();
    return $detector->isTablet();
});
Plugin::load('Muffin/Footprint');
if (Configure::read('debug')) {
    Plugin::load('DebugKit', ['bootstrap' => true]);
}
DispatcherFactory::add('Asset');
DispatcherFactory::add('Routing');
DispatcherFactory::add('ControllerFactory');`

我一直认为,日期时间字段将被修补到 patchEntity() 中的 Chronos / DateTime 对象。我在这里错了吗?有没有最佳实践? 关于日期格式,我没有以任何方式修改 bootstrap.php。谢谢!

【问题讨论】:

  • 请务必提及您正在使用的确切 CakePHP 版本,情况时不时会发生变化。另外请显示您的引导程序中的实际内容,同样,随着时间的推移,事情确实会发生变化,尤其是应用程序模板的默认日期/时间配置已经更改了很多次。
  • 我的蛋糕版本是 3.3.13 。 bootstrap.php 没有被修改。
  • 再一次,应用模板引导程序已经随着时间的推移而改变,所以说你没有修改它并没有真正的帮助,因为没有人知道你使用的是什么版本(应用模板和 CakePHP 框架是两个不同的存储库)。
  • 哦,对不起,我的项目不是用 cakePHP 框架应用程序项目构建的。

标签: validation datetime cakephp


【解决方案1】:

您尚未更改datetime 数据库类型的默认配置,这要求输入格式为Y-m-d H:i:s。当遇到不同的格式时,类型类将按原样返回输入值,即不被编组。

如果您需要以不同的格式接受您的日期,例如,您可以配置现有的 datetime 类型,以便将其应用于全局编组(即适用于所有类型为 DATETIME/TIMESTAMP 的列):

\Cake\Database\Type::build('datetime')
    ->useLocaleParser()
    ->setLocaleFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");

如果您希望它仅应用于特定模型/列,那么您可以创建并使用自定义类型(只需扩展 \Cake\Database\Type\DateTimeType 就足够了)而不是 datetime,并将其应用于您的模型您需要的架构:

// in src/Database/Type/CustomDateTimeType.php

namespace App\Database\Type;

use Cake\Database\Type\DateTimeType;

class CustomDateTimeType extends DateTimeType
{
}
// in the respective table class

protected function _initializeSchema(\Cake\Database\Schema\Table $schema)
{
    // ...
    $schema->columnType('launchdate', 'customDateTime');
    return $schema;
}
// in config/bootstrap.php

use Cake\Database\Type;

Type::map('customDateTime', 'App\Database\Type\CustomDateTimeType');
Type::build('customDateTime')
    ->useLocaleParser()
    ->setLocaleFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");

另见

【讨论】:

  • 太棒了!你总是解释得很好。
  • 非常感谢您的详细回答。我必须将格式更改为“yyyy-MM-dd'T'HH:mm:ss.SSS'Z'”才能将其转换为数据库的正确值。但它仍然不会通过 datetime() 验证器。
  • @Seb 不需要像这样更改格式,除非您只想接受带有Z 时区的日期,因为您在那里所做的会将时区标识符硬编码为@ 987654335@。编组和验证是两个独立的过程,使用这种格式,您需要一个自定义验证规则,分别是一个自定义 datetime 验证器正则表达式模式:stackoverflow.com/questions/34896273/…
猜你喜欢
  • 2019-09-26
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-03
  • 2019-04-08
相关资源
最近更新 更多