我尝试从 cakephp 3 表单中保存数据。所有数据都保存得很好,但日期时间没有。我有 2 个日期时间字段。这些字段由 jquery-ui 小部件填充。
问题似乎发生在对实体进行打包时。
$intervention = $this->Interventions->patchEntity($intervention, $this->request->data);
'user_id' => '1',
'description' => 'test',
'starttime' => '2015/11/15 10:00',
'endtime' => '2015/11/15 12:10'
对象(应用程序\模型\实体\干预)
'id' => (int) 3,
'user_id' => (int) 1,
'description' => 'test',
'starttime' => null,
'endtime' => null
...
starttime 和 endtime 变为 null,我不明白为什么。
有人以前有这个铅吗?
我尝试(用于调试和理解)在修补后强制字段值
和 mysql 中的日期时间字段都可以。
$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']));
感谢帮助
最佳答案
日期/时间值正在以区域设置感知方式进行转换/解析
更新:这是 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);
需要注意的是,这将影响所有日期/时间输入,而不仅仅是您的
starttime
和 endtime
领域!另一方面,如果 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
关于datetime - 为什么在修补/保存时日期/时间值解释不正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33734683/