如何处理包含Laravel上的碳日期的模型的JSON响应?

Mau*_*uro 9 javascript json backbone.js laravel-4 php-carbon

我正在编写一个非常简单的应用程序,要求Backbone.js模型和Laravel 4模型同步.当Laravel模型涉及日期时,就会出现问题.我的Laravel控制器看起来像这样:

class OrderController extends \BaseController {
    ...
    public function update($id = null) {
        ...
        if (Request::ajax()) 
            return $order;
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这成功响应了$ order的JSON表示,客户端用它来保持同步.但是,Carbon日期作为Carbon对象表示返回,如下所示:

{
    "delivered_at":{"date":"2014-02-25 12:55:29","timezone_type":3,"timezone":"America\/Argentina\/Buenos_Aires"}
}
Run Code Online (Sandbox Code Playgroud)

我可以设法将此解释为javascript Date对象,但是,当此对象返回到laravel时,JSON将删除Carbon该类,而Eloquent 无法将其作为日期读取:

[2014-02-25 12:58:32] log.ERROR: exception 'ErrorException' with message 'preg_match() expects parameter 2 to be string, array given' in vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:2210
Stack trace:
#0 [internal function]: Illuminate\Exception\Handler->handleError(2, 'preg_match() ex...', '/Users/maurospi...', 2210, Array)
#1 vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(2210): preg_match('/^(\d{4})-(\d{2...', Array)
#2 vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(2151): Illuminate\Database\Eloquent\Model->fromDateTime(Array)
#3 vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(306): Illuminate\Database\Eloquent\Model->setAttribute('delivered_at', Array)
#4 app/controllers/OrderController.php(120): Illuminate\Database\Eloquent\Model->fill(Array)
#5 [internal function]: OrderController->update('91')
#6 vendor/laravel/framework/src/Illuminate/Routing/Controllers/Controller.php(138): call_user_func_array(Array, Array)
#7 vendor/laravel/framework/src/Illuminate/Routing/Controllers/Controller.php(115): Illuminate\Routing\Controllers\Controller->callMethod('update', Array)
#8 vendor/laravel/framework/src/Illuminate/Routing/Router.php(985): Illuminate\Routing\Controllers\Controller->callAction(Object(Illuminate\Foundation\Application), Object(Illuminate\Routing\Router), 'update', Array)
#9 [internal function]: Illuminate\Routing\{closure}('91')
#10 vendor/laravel/framework/src/Illuminate/Routing/Route.php(80): call_user_func_array(Object(Closure), Array)
#11 vendor/laravel/framework/src/Illuminate/Routing/Route.php(47): Illuminate\Routing\Route->callCallable()
#12 vendor/laravel/framework/src/Illuminate/Routing/Router.php(1016): Illuminate\Routing\Route->run(Object(Illuminate\Http\Request))
#13 vendor/laravel/framework/src/Illuminate/Foundation/Application.php(574): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#14 vendor/laravel/framework/src/Illuminate/Foundation/Application.php(550): Illuminate\Foundation\Application->dispatch(Object(Illuminate\Http\Request))
#15 public/index.php(49): Illuminate\Foundation\Application->run()
#16 {main} [] []
Run Code Online (Sandbox Code Playgroud)

所以我要么:

  1. 扩展JsonResponse类以将Carbon日期转换为字符串表示.
  2. 扩展Eloquent类以将Carbon类结构的StdClass对象解释为日期.
  3. 做一些我显然缺少的东西,Laravel 4声称在REST中很棒,所以我想我错过了一些东西.

Blu*_*nie 5

首先,我建议您将 API 与控制器分开。使用资源进行 API 调用。

对于返回到 Laravel 的对象,我不知道您如何处理它以获取错误,但如果您想要一个 Carbon 日期,您应该启动一个新的 Carbon 实例。否则,您可以只将日期作为字符串返回,Laravel 的模型将处理其余的事情。

假设返回的对象是:

{
    "delivered_at":{"date":"2014-02-25 12:55:29","timezone_type":3,"timezone":"America\/Argentina\/Buenos_Aires"}
}
Run Code Online (Sandbox Code Playgroud)

变量 $data 将具有当前响应,您可以简单地覆盖 Delivered_at:

$data->delivered_at = $data->delivered_at->date;
Run Code Online (Sandbox Code Playgroud)

或者如果你想要一个 Carbon 对象:

$data->delivered_at = new \Carbon\Carbon($data->delivered_at->date, $data->delivered_at->timezone);
Run Code Online (Sandbox Code Playgroud)


caf*_*nso 5

这可能会有点晚,但我通常会使用访问器和更改器来实现这一点.例如,如果我希望所有created_atupdated_at字段始终以ATOM格式返回,我创建一个扩展的基础模型类Eloquent,其他每个模型都继承:

use Carbon\Carbon as Carbon;
use Illuminate\Database\Eloquent\Model as Model;

class BaseModel extends Model {

    public function getCreatedAtAttribute($value)
    {
        return Carbon::parse($value)->toATOMString();
    }

    public function setCreatedAtAttribute($value)
    {
        $this->attributes['created_at'] = Carbon::parse($value)->toDateTimeString();
    }

    public function getUpdatedAtAttribute($value)
    {
        return Carbon::parse($value)->toATOMString();
    }

    public function setUpdatedAtAttribute($value)
    {
        $this->attributes['created_at'] = Carbon::parse($value)->toDateTimeString();
    }
}
Run Code Online (Sandbox Code Playgroud)