2015-06-06 18 views
14

Ho una messa a punto del modello come così:Includere rapporti modello in risposta JSON utilizzando eloquente e laravel 5

<?php namespace App\Models; 

use Illuminate\Database\Eloquent\Model; 

class Upload extends Model { 

    /** 
    * The database table used by the model. 
    * 
    * @var string 
    */ 
    protected $table = 'uploads'; 

    /** 
    * The attributes excluded from the model's JSON form. 
    * 
    * @var array 
    */ 
    protected $hidden = array('id', 'user', 'created_at', 'updated_at'); 

    public function mime() { 
     return $this->hasOne('App\Models\Mime', 'mime'); 
    } 
} 

E quando JsonSerialize() viene chiamato, restituisce:

{ 
    "serverPath": "upload/2015/06/06/21/filename.jpg", 
    "filename": "filename.jpg", 
    "mime": "92" 
} 

Questo 92 riferimenti l'id in un'altra tabella (che rappresenta App\Models\Mime) con una stringa, type, associata ad essa. Vorrei sostituire questo 92 con detta stringa.

{ 
    "serverPath": "upload/2015/06/06/21/filename.jpg", 
    "filename": "filename.jpg", 
    "mime": "image/jpeg" 
} 

Com'è possibile? Ho provato alcune cose con protected $appends nel modello Upload, ma non sono sicuro di comprendere appieno come utilizzare/accedere alle relazioni all'interno del modello.

Chiarimento La tabella mimi contiene colonne id e type, mentre la tabella arrivi contiene una colonna integer chiamato mime che fa riferimento a un id in mimi

+1

Vorrei solo dire -> con ('mimo') quando sto tornando esso - fa questo aiuto? Per esempio 'return \ Upload :: find (1) -> with ('mime');' – haakym

+0

Dove andrebbe una cosa del genere? Intendi quando restituisco il modello 'Upload' in un'altra funzione? '\ App \ Models \ Upload :: findOrFail (1) -> with ('mime')' restituisce solo '{}' quando viene chiamato 'JsonSerialize' su di esso –

+0

Bene, come lo stai restituendo ora? Si prega di aggiornare la tua domanda con questo come potrebbe dare un contesto migliore. Inoltre, potresti provare a non chiamare JsonSerialize. Penso che tutti i modelli Eloquent siano automaticamente convertiti in JSON, oppure puoi fare '-> toJson()' su un modello Eloquent. – haakym

risposta

26

non è una buona idea di nominare un rapporto lo stesso nome di uno dei campi sul tavolo. Ciò causa problemi (come hai scoperto) quando si tenta di accedere alla relazione rispetto all'accesso al campo.

Idealmente, il campo mime deve essere rinominato in mime_id. Questo è conforme alle convenzioni di Laravel ed è un nome più preciso per il campo.

Tuttavia, se non si ha la possibilità di modificare il nome del campo, è necessario modificare il nome della relazione.

class Upload extends Model { 
    protected $hidden = array('id', 'user', 'created_at', 'updated_at'); 

    public function uploadMime() { 
     return $this->belongsTo('App\Models\Mime', 'mime'); 
    } 
} 

Nella classe superiore, il nome della relazione è ora uploadMime. Inoltre, la relazione è stata modificata da hasOne a belongsTo. Poiché la tabella dei caricamenti ha la chiave esterna della tabella dei mimi, il modello di caricamento appartiene al modello Mime (e il modello Mime haOne/ha molti modelli di caricamento).

Ora, il codice dovrebbe essere simile:

$data = \App\Models\Upload::with('uploadMime')->findOrFail(1); 
return new JsonResponse($data); 

Questo dovrebbe dare qualcosa in uscita lungo le linee di:

{ 
    "serverPath": "upload/2015/06/06/21/filename.jpg", 
    "filename": "filename.jpg", 
    "mime": "92", 
    "uploadMime": { 
     "id": 92, 
     "type": "image/jpeg" 
    } 
} 

Modifica JSON utilizzando $appends e l'attributo di accesso

Se volevi avvicinarti all'output JSON che hai fornito nella tua domanda, puoi cr EATE una funzione di accesso mimeType e aggiungerlo alla proprietà $appends:

class Upload extends Model { 
    // hide the mime field and uploadMime data 
    protected $hidden = array('id', 'user', 'created_at', 'updated_at', 'mime', 'uploadMime'); 

    // add the mimeType attribute to the array 
    protected $appends = array('mimeType'); 

    // code for $this->mimeType attribute 
    public function getMimeTypeAttribute($value) { 
     $mimeType = null; 
     if ($this->uploadMime) { 
      $mimeType = $this->uploadMime->type; 
     } 
     return $mimeType; 
    } 

    public function uploadMime() { 
     return $this->belongsTo('App\Models\Mime', 'mime'); 
    } 
} 

Questo dovrebbe dare qualcosa in uscita lungo le linee di:

{ 
    "serverPath": "upload/2015/06/06/21/filename.jpg", 
    "filename": "filename.jpg", 
    "mimeType": "image/jpeg" 
} 

Modifica JSON sovrascrivendo la funzione

toArray() In alternativa, se si desidera realmente che JSON utilizzi la chiave mime, è possibile modificare direttamente il metodo toArray():

class Upload extends Model { 
    // hide uploadMime data, but not the mime field 
    protected $hidden = array('id', 'user', 'created_at', 'updated_at', 'uploadMime'); 

    public function uploadMime() { 
     return $this->belongsTo('App\Models\Mime', 'mime'); 
    } 

    // override the toArray function (called by toJson) 
    public function toArray() { 
     // get the original array to be displayed 
     $data = parent::toArray(); 

     // change the value of the 'mime' key 
     if ($this->uploadMime) { 
      $data['mime'] = $this->uploadMime->type; 
     } else { 
      $data['mime'] = null; 
     } 

     return $data; 
    } 
} 

Questo dovrebbe dare qualcosa in uscita lungo le linee di:

{ 
    "serverPath": "upload/2015/06/06/21/filename.jpg", 
    "filename": "filename.jpg", 
    "mime": "image/jpeg" 
} 
+0

Questo è perfetto! Molte grazie. –

+0

è applicabile in 5.2? – user3779015

+0

@ user3779015 sì, le informazioni qui sono ancora rilevanti per 5.2. – patricus

0

Va bene Credo che questo è ciò che sei cercando ...

Upload.php (nessuna modifica qui)

<?php namespace App\Models; 

use Illuminate\Database\Eloquent\Model; 

class Upload extends Model { 

    /** 
    * The database table used by the model. 
    * 
    * @var string 
    */ 
    protected $table = 'uploads'; 

    /** 
    * The attributes excluded from the model's JSON form. 
    * 
    * @var array 
    */ 
    protected $hidden = array('id', 'user', 'created_at', 'updated_at'); 

    public function mime() { 
     return $this->hasOne('App\Models\Mime', 'mime'); 
    } 
} 

Allora avete il vostro modello di Mime

Mime.php

<?php namespace App\Models; 

use Illuminate\Database\Eloquent\Model; 

class Mime extends Model { 

    /** 
    * The database table used by the model. 
    * 
    * @var string 
    */ 
    protected $table = 'mimes'; 

} 

se fate questo per un test Credo che si dovrebbe vedere il tipo

routes.php

Route::get('test', function() { 
    $upload = \Upload::with('mime')->first(); 
    // return $upload //here would return it as JSON I'm pretty sure! 
    return $upload->mime->type; 
}); 

Controllate la documentazione per ulteriori dettagli sulle eager loading: http://laravel.com/docs/5.0/eloquent#eager-loading

+0

Questo sta restituendo l'errore: QueryException in Connection.php line 624: SQLSTATE [42S22]: Column non trovata: 1054 Colonna sconosciuta 'mimes.mime' in 'where clausola' (SQL: select * from 'mimes' dove' mimes' .mime' in (826)). Se aiuta, la tabella 'mimes' contiene le colonne' id' e 'type', mentre' uploads 'contiene una colonna intera chiamata 'mime' che fa riferimento a' id' in 'mimes' –

+0

Modificata la relazione con' return $ this -> hasOne ('App \ Models \ Mime', 'id', 'mime'); 'che ha risolto l'errore SQL. Anche se ora il problema è che '$ upload-> mime' non è un oggetto, ma solo l'id. –

+1

Controlla la risposta @partricus, è esattamente quello che aggiorno anche la mia risposta se non l'avesse già pubblicato – haakym

Problemi correlati