我有一个带有日期变换器的模型,例如 created_at
. 让我们说一个通用的 timestamp
属性 .
当以JSON格式从客户端传递数据时,我会得到
{
timestamp: "2016-06-07T22:00:00.000Z"
}
该属性将用于设置一些模型,如下所示:
$model = new Foo();
$model->timestamp = Input::get('timestamp');
由于这将触发日期变更器,因此调用php Carbon
并失败
InvalidArgumentException in Carbon.php line 425
Unexpected data found.
Trailing data
现在,这不是Carbon本身的问题,它能够处理JSON格式 . 如果你试试
new Carbon('2016-06-07T22:00:00.000Z');
你实际上得到了预期的结果 .
从我看到的,问题起源于一个奇怪的Eloquent行为 . 从上面提到的 InvalidArgumentException in Carbon.php line 425
看到这条踪迹:
in Carbon.php line 425
at Carbon::createFromFormat('Y-m-d H:i:s', '2016-06-07T22:00:00.000Z') in Model.php line 2915
at Model->asDateTime('2016-06-07T22:00:00.000Z') in Model.php line 2871
at Model->fromDateTime('2016-06-07T22:00:00.000Z') in Model.php line 2826
at Model->setAttribute('timestamp', '2016-06-07T22:00:00.000Z') in Model.php line 3351
Eloquent试图传递一个 bad format ,它没有镜像实际的JSON格式,这导致了Carbon异常 .
另一方面,像上面提到的 new Carbon($jsonDate)
这样的简单调用在这种情况下可以正常工作 .
-
我应该如何解决这个问题?
-
这不应该是一个雄辩的错误吗?
== EDIT ==
我自己没有编码任何增变器 . 我正在使用默认的日期变更器,如下所示:
public function getDates() {
return ['timestamp'];
}
1 回答
当在
getDates
函数中设置属性时,Eloquent会分析您提供的日期 .在它的分析中它有四个步骤:(见
Modal.php
asDateTime
方法澄清,代码相当好评论:https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L2898)如果它已经是Carbon实例,请使用它
如果它是实现DateTimeInterface的实例,请使用它
如果是数字,则解析为Unix时间戳
如果是简单的年月日格式(由正则表达式尝试)使用它
如果以上都不是,请使用您指定为默认的格式创建Carbon实例
在你的情况下,1-4不匹配,所以它尝试5 .
您没有在模型上指定自定义dateFormat,因此它使用适用于您正在使用的数据库连接类型的默认日期格式 . 您可以通过向模型添加$ dateFormat变量来覆盖它:
protected $dateFormat = 'U';
但是您的正常时间戳可能已经是正确的格式 . 所以这个解决方案对你不起作用 .
在你的情况下,我会这样做:
$model->timestamp = Carbon::parse(Input::get('timestamp'));
或者使用适当格式的
Carbon::createFromFormat()
.我不知道他们为什么不直接用Carbon解析它 . 我想它更容易出错并且可控性更低 . 使用不同的国际格式,您可能会得到意想不到的结果(月和日切换等) . 它也可能比他们目前的做法慢 .