2017-02-06 49 views
0

我試圖驗證cakePHP 3(3.3.13)中的日期。我收到的數據採用帶時區的ISO 8601格式,如2017-02-17T23:00:00.000Z。CakePHP 3日期時間驗證Iso 8601及時區

我有一個簡單的$validator->date()規則,總是無法驗證日期。我嘗試使用我自己的驗證提供程序,其中我使用提供的值構建Chronos對象。由於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');` 

我一直認爲,一個DateTime字段會修補patchEntity()中的Chronos/DateTime對象。我錯了嗎?有沒有最佳實踐? 我沒有以任何方式修改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'」以將其轉換爲數據庫的正確值。但它仍然不會通過datetime()驗證器。 – Seb

+0

@Seb不需要改變這樣的格式,除非你只想接受帶有'Z'時區的日期,因爲你在那裏做的事會將時區標識符硬編碼爲'Z'。編組和驗證是兩個獨立的過程,具有這種格式,您需要一個自定義驗證規則,分別是自定義的'datetime'驗證器正則表達式模式:** http://stackoverflow.com/questions/34896273/cakephp-3-解析最新與 - localstringformat到正確-SQL格式和糾正/ 34896974#34896974 ** – ndm