Question

J'écris une application assez simple qui nécessite que les modèles Backbone.js et Laravel 4 soient synchronisés.Des problèmes surgissent lorsque les modèles Laravel impliquent Carbone Rendez-vous.Mon contrôleur Laravel ressemble à ceci :

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

Cela répond avec succès avec une représentation JSON de $order que le côté client utilise pour rester synchronisé.Cependant, les dates Carbon sont renvoyées en tant que représentation de l'objet Carbon, comme ceci :

{
    "delivered_at":{"date":"2014-02-25 12:55:29","timezone_type":3,"timezone":"America\/Argentina\/Buenos_Aires"}
}

Je pourrais réussir à interpréter cela comme un objet Date javascript assez facilement, cependant, lorsque cet objet retourne à Laravel, JSON supprime le Carbon class et Eloquent ne parvient pas à lire cela comme une date :

[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} [] []

Donc je dois soit :

  1. Étendez la classe JsonResponse pour convertir les dates Carbon en représentations sous forme de chaîne.
  2. Étendez la classe Eloquent pour interpréter les objets StdClass du Carbon structure de classe aux dates.
  3. Faites quelque chose qui me manque clairement, Laravel 4 prétend être génial chez REST donc je suppose qu'il me manque quelque chose.
Était-ce utile?

La solution

Tout d’abord, je vous suggère de séparer l’API des contrôleurs.Utilisez des ressources pour les appels d'API.

Pour l'objet renvoyé à Laravel, je ne sais pas comment le traitez-vous pour obtenir l'erreur, mais vous devez lancer une nouvelle instance Carbon si vous souhaitez une date Carbon.Sinon, vous pouvez simplement renvoyer la date sous forme de chaîne, le modèle de Laravel s'occupera du reste.

En supposant que l'objet renvoyé est :

{
    "delivered_at":{"date":"2014-02-25 12:55:29","timezone_type":3,"timezone":"America\/Argentina\/Buenos_Aires"}
}

Et la variable $data aura la réponse actuelle, vous pouvez simplement écraser delivery_at :

$data->delivered_at = $data->delivered_at->date;

Ou si vous voulez un objet Carbone :

$data->delivered_at = new \Carbon\Carbon($data->delivered_at->date, $data->delivered_at->timezone);

Autres conseils

Cela peut arriver un peu tard, mais j'utilise généralement des accesseurs et des mutateurs pour y parvenir.Par exemple, si je veux tout created_at et updated_at champs à retourner toujours au format ATOM, je crée une classe de modèle de base s'étendant Eloquent dont tous les autres modèles héritent :

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();
    }
}

Ce n'est peut-être pas la même chose, mais j'obtiendrais cette erreur lorsque je travaillais avec des horodatages et du carbone, mais l'utilisation de strtotime() sur les données que je transmettais a résolu mon problème, peut vous aider.

La façon dont vous gérez les dates dans le backbone et dans Laravel aura un impact.
Vous devez choisir un format de date et vous y tenir.Et puis assurez-vous que les deux parties se convertissent à ce format lors de la transmission des données au JS et aux contrôleurs.

Si vous envoyez un objet Date JavasScript pur, il renvoie une chaîne de date qui ressemble à ceci
"Sat Apr 19 2014 00:00:00 GMT+0200 (South Africa Standard Time)"
Ce qui n'est pas si agréable, puisque PHP strtotime finit par l'analyser de manière géniale.

Voici un exemple:

$jsdate = "Sat Apr 19 2014 00:00:00 GMT+0200 (South Africa Standard Time)";
$carbon = Carbon::createFromTimestamp(strtotime($jsdate));
$iso8601 = $carbon ->format(Carbon::ISO8601)
//output '1970-01-01T02:00:00+0200' which is a UNIX timestamp 0.

Pourquoi cette date ? peut-être que quelqu'un d'autre pourra mieux élaborer que moi.Vous pouvez utiliser un format de date personnalisé pour le lire correctement, mais utilisez plutôt un format que les deux peuvent comprendre.

Comme ISO8601

//javascript
var jsdate = (new Date()).toISOString();

Et en php, Carbon devrait pouvoir le gérer sans problème

Si vous souhaitez obtenir la colonne de date de votre modèle (created_at) au format chaîne à utiliser comme ceci :

$response['created_at'] = Carbon::parse($model->created_at)->toDateString();

cela va changer

created_at = {"date":"2014-02-25 12:55:29","timezone_type":3,"timezone":"America\/Argentina\/Buenos_Aires"}

dans ceci :

created_at = "2014-02-25 12:55:29"

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top