2017-02-06 16 views
0

Я пытаюсь проверить дату в cakePHP 3 (3.3.13). Данные, которые я получаю, находятся в формате ISO 8601 с часовым поясом, например, 2017-02-17T23: 00: 00.000Z.CakePHP 3 DateTime Validation Iso 8601 с часовым поясом

У меня есть правило $validator->date(), которое всегда не подтверждает дату. Я попытался использовать свой собственный поставщик валидации, в котором я создаю объект Chronos из предоставленного значения. Как Хронос с использованием DateTimeInterface в succeds проверки, но я получаю сообщение об ошибке 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');` 

Я всегда думал, что поле даты и времени будет исправлено до объекта Chronos/DateTime в patchEntity(). Я здесь не прав? Есть ли лучшие практики? Я не модифицировал bootstrap.php каким-либо образом относительно форматов даты. Спасибо!

+1

Мольба se всегда упоминает точную версию CakePHP, которую вы используете, вещи меняются сейчас и потом. Также, пожалуйста, покажите, что на самом деле находится в вашем загрузочном блоке, как и все, что-то меняется со временем, особенно в настройках даты и времени по умолчанию шаблонов приложений было изменено несколько раз. – ndm

+0

Моя версия торта - 3.3.13. Bootstrap.php не был изменен. – Seb

+0

Опять же, загрузочный шаблон шаблонов приложений был изменен с течением времени, поэтому, говоря, что вы его не модифицировали, на самом деле не помогает, так как никто не может определить, какую версию вы используете (шаблон приложения и CakePHP рамки - два разных хранилища). – ndm

ответ

2

Вы не изменили конфигурацию базы данных datetime по умолчанию, которая требует, чтобы входной сигнал находился в формате Y-m-d H:i:s. Когда встречается другой формат, класс типа возвращает возвращаемое значение как есть, т. Е. Оно не сортируется.

Если вам нужны ваши даты, чтобы быть принятым в другом формате, вы можете, например, настроить существующий datetime типа для того, чтобы это обратиться к mashalling глобально (т.е. для всех столбцов, типа 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"); 

Смотрите также

+0

Отлично! Вы всегда хорошо объясняете. –

+0

Спасибо за подробный ответ. Мне пришлось изменить формат на «yyyy-MM-dd'T'HH: mm: ss.SSS'Z», чтобы преобразовать его в правильное значение для базы данных. Но он все равно не пройдет проверку достоверности(). – Seb

+0

@Seb Изменение формата, подобного этому, не требуется, если только вы не хотели принимать только даты с часовым поясом 'Z', так как то, что вы делаете, будет жестко задавать идентификатор часового пояса на' Z'. Маршаллинг и валидация - это два отдельных процесса с таким форматом, вам потребуется специальное правило проверки, например, шаблон регулярного выражения валидатора 'datetime': ** http: //stackoverflow.com/questions/34896273/cakephp-3- синтаксический-дата-с-localstringformat-к-правильному-SQL-формата-и-правильный/34896974 # 34896974 ** – ndm