Laravel5 Eloquent默认日期变更器失败并带有JSON日期输入

时间:2016-06-10 12:03:31

标签: php json laravel laravel-5

我有一个带有日期变更器的模型,例如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');

你实际上得到了预期的结果。

从我看到的,问题起源于一种奇怪的雄辩行为。请参阅上面提到的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正在尝试createFromFormat传递格式错误,它不会反映实际的JSON格式,这会导致Carbon异常。

另一方面,像上面提到的new Carbon($jsonDate)之类的简单调用在这种情况下可以正常工作。

  1. 我应该如何解决这个问题?
  2. 这不应该是一个雄辩的错误吗?
  3. ==编辑==

    我自己没有对任何增变器进行编码。我使用默认的日期变更器如下:

    public function getDates() {
        return ['timestamp'];
    }
    

1 个答案:

答案 0 :(得分:1)

当在getDates函数中设置属性时,Eloquent会分析您提供的日期。

在其分析中,它有四个步骤:(请参阅Modal.php asDateTime方法进行说明,代码评论非常好:https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L2898

  1. 如果它已经是Carbon实例,请使用
  2. 如果是实现DateTimeInterface的实例,请使用
  3. 如果是数字,则解析为Unix时间戳
  4. 如果是简单的年月日格式(由正则表达式尝试),请使用
  5. 如果以上都不是,请使用您指定为默认格式的
  6. 创建Carbon实例

    在你的情况下,1-4不匹配,所以尝试5。

    您没有在模型上指定自定义dateFormat,因此它使用适用于您正在使用的数据库连接类型的默认日期格式。您可以通过向模型添加$ dateFormat变量来覆盖它:

    protected $dateFormat = 'U';

    但是你的正常时间戳可能已经是正确的格式了。所以这个解决方案对你不起作用。

    在你的情况下,我会这样做: $model->timestamp = Carbon::parse(Input::get('timestamp'));

    或者使用具有适当格式的Carbon::createFromFormat()

    我不知道他们为什么不直接用Carbon解析它。我想它更容易出错并且不太可控。使用不同的国际格式,您可能会得到意想不到的结果(月和日切换等)。它也可能比他们目前的做法慢。