修补/保存时,为什么日期/时间值解释不正确?

时间:2015-11-16 11:50:10

标签: datetime cakephp internationalization marshalling cakephp-3.0

我尝试从cakephp 3表格中保存数据。所有数据都保存得很好,但日期时间没有。我有2个日期时间字段。这些字段由jquery-ui小部件填充。

当实体化时,问题似乎发生了。

$intervention = $this->Interventions->patchEntity($intervention, $this->request->data);
  • 调试$ this-> request-> data:

    'user_id' => '1',
    'description' => 'test',
    'starttime' => '2015/11/15 10:00',
    'endtime' => '2015/11/15 12:10'
    
  • 在pacthEntity之后调试我的对象$干预:

对象(App \ Model \ Entity \ Intervention)

'id' => (int) 3,
'user_id' => (int) 1,
'description' => 'test',
'starttime' => null,
'endtime' => null
...

starttime和endtime变为null,我不明白为什么。

以前有人有这个pb吗?

我尝试(用于调试和理解)在修补时强制字段值 和mysql中的datetime字段都可以。

$intervention->starttime = date('Y-m-d H:i:s', strtotime($this->request->data['starttime'])); 
$intervention->endtime = date('Y-m-d H:i:s', strtotime($this->request->data['endtime']));

感谢您的帮助

1 个答案:

答案 0 :(得分:19)

日期/时间值以区域设置感知方式

进行转换/解析

更新:这是3.2.5之前的CakePHP应用程序模板版本的默认行为。从3.2.5开始,默认情况下不再启用语言环境解析,这将使日期/时间编组逻辑期望默认格式为Y-m-d H:i:s

在编组过程中,根据相应的列类型对值进行“转换”。对于DATETIME列,这由\Cake\Database\Type\DateTimeType类型类完成。

确切地说,这是在 \Cake\Database\Type\DateTimeType::marshall() 中完成的。

使用默认的应用模板配置,DateTimeType配置为使用区域设置感知解析,并且由于未设置默认的区域设置格式, \Cake\I18n\Time::parseDateTime() 将根据值解析值默认为“字符串格式”( Time::$_toStringFormat ),默认为区域设置[IntlDateFormatter::SHORT, IntlDateFormatter::SHORT]

因此,如果您的语言环境设置为en_US,那么该值将使用预期格式M/d/yy, h:mm a进行解析,您的值不适合,因此您最终最终为实体属性设置了null

使解析器使用正确的格式

TL;博士

如果jQuery小部件的格式未在应用程序的任何位置使用,您可以例如临时设置正确的区域设置格式,或者禁用区域设置解析,例如

// for time- or date-only comlumn types you'd use 'time' or 'date' instead of 'datetime'
$dateTimeType = Type::build('datetime')->setLocaleFormat('yyyy/MM/dd HH:mm');

// ...
$intervention = $this->Interventions->patchEntity($intervention, $this->request->data);
// ...

$dateTimeType->setLocaleFormat(null);

$dateTimeType = Type::build('datetime')->useLocaleParser(false);

// ...
$intervention = $this->Interventions->patchEntity($intervention, $this->request->data);
// ...

$dateTimeType->useLocaleParser(true);

应该注意,这会影响所有日期/时间输入,而不仅仅是starttimeendtime字段!

另一方面,jQuery小部件使用的格式应该是您希望在应用程序中使用的格式,然后更改默认格式也可以这样做,例如

use Cake\I18n\Time;
use Cake\I18n\FrozenTime;

// To affect date-only columns you'd configure `Date` and `FrozenDate`.
// For time-only columns, see the linked SO question below.
Time::setToStringFormat('yyyy/MM/dd HH:mm');
FrozenTime::setToStringFormat('yyyy/MM/dd HH:mm');

bootstrap.php中。请注意,您可能还需要修改Time/FrozenTime::setJsonEncodeFormat()Time/FrozenTime::$niceFormat

另见

在编组之前转换输入

另一种选择是在编组过程之前将数据转换为Time个实例。这可以避免前面提到的解决方案可能会影响所有输入的问题。

在您的InterventionsTable课程中(也可以放入行为或外部听众):

use Cake\Event\Event;
use Cake\I18n\Time;

...

public function beforeMarshal(Event $event, \ArrayObject $data, \ArrayObject $options)
{
    foreach (['starttime', 'endtime'] as $key) {
        if (isset($data[$key]) && is_string($data[$key])) {
            $data[$key] = Time::parseDateTime($data[$key], 'yyyy/MM/dd HH:mm');
        }
    }
}

另见

<强> Cookbook > Database Access & ORM > Saving Data > Modifying Request Data Before Building Entities