2015-06-06 1 views
14

У меня есть настройки модели, как так:Включить модели отношений в ответ JSON с помощью красноречивых и 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'); 
    } 
} 

И когда JsonSerialize() называется, она возвращает:

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

Это 92 референции идентификатор в другой таблице (которая представляет App\Models\Mime) со строкой, связанной с ней type. Я хотел бы заменить эту строку 92 на указанную строку.

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

Как это возможно? Я пробовал некоторые вещи с protected $appends в модели Upload, но я не уверен, что полностью понимаю, как использовать/получать доступ к отношениям внутри модели.

Разъяснение Таблица мимы содержит столбцы id и type, в то время как таблица загрузки содержит целочисленный столбец mime, который ссылается на идентификатор в мимы

+1

Я бы просто сказать -> с («мим»), когда я возвращаюсь это - это поможет? Например, 'return \ Upload :: find (1) -> with ('mime');' – haakym

+0

Где бы это было? Вы имеете в виду, когда я возвращаю модель «Загрузить» в другой функции? '\ App \ Models \ Upload :: findOrFail (1) -> with ('mime')' возвращает только '{}', когда на него вызывается 'JsonSerialize' –

+0

Ну, как вы возвращаете его сейчас? Пожалуйста, обновите свой вопрос, поскольку это может дать лучший контекст. Кроме того, не могли бы вы попытаться не вызвать JsonSerialize. Я думаю, что все модели Eloquent автоматически преобразуются в JSON, или вы можете делать '-> toJson()' в модели Eloquent. – haakym

ответ

26

Это не является хорошей идеей назвать Взаимоотношениях такое же имя, как одно из полей на столе. Это вызывает проблемы (как вы выяснили) при попытке получить доступ к зависимости от доступа к полю.

В идеале ваше поле mime должно быть переименовано в mime_id. Это соответствует соглашениям Ларавеля и является более точным названием для поля.

Однако, если у вас нет возможности изменить имя поля, вы должны изменить имя отношения.

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

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

В приведенном выше класс, имя отношения теперь uploadMime. Кроме того, отношение было изменено с hasOne на belongsTo. Так как ваша таблица загрузок имеет внешний ключ для таблицы mimes, то модель загрузки принадлежит модели Mime (а модель Mime имеет одну или несколько моделей загрузки).

Теперь код должен выглядеть примерно так:

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

Это должно дать вам выход что-то вдоль линий:

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

разделе Изменение JSON с помощью $appends и атрибут Accessors

Если вы хотите приблизиться к выходу JSON, который вы предоставили в своем вопросе, вы можете cr ЭАТС в mimeType аксессор и добавить его в $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'); 
    } 
} 

Это должно дать вам выход что-то вдоль линий:

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

разделе Изменение JSON переопределением toArray() функцию

Или, если вы действительно хотите, чтобы JSON использовал ключ mime, вы можете напрямую изменить метод 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; 
    } 
} 

Это должно дать вам выход что-то вдоль линий:

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

Это прекрасно! Большое спасибо. –

+0

это применимо в 5.2? – user3779015

+0

@ user3779015 да, информация здесь по-прежнему актуальна для 5.2. – patricus

0

Хорошо, я считаю, что это то, что вы ищет ...

Upload.php (без изменений здесь)

<?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'); 
    } 
} 

Тогда у вас есть модель Мим

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'; 

} 

, если вы сделаете это для теста я считаю, вы должны увидеть тип

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

Проверить документы для получения более подробной информации о нетерпеливой загрузки: http://laravel.com/docs/5.0/eloquent#eager-loading

+0

Это возвращает ошибку: QueryException в строке Connection.php 624: SQLSTATE [42S22]: столбец не найден: 1054 Неизвестный столбец «mimes.mime» в «where clause» (SQL: select * from 'mimes' где' mimes'.'mime' в (826)). Если это помогает, таблица 'mimes' содержит столбцы' id' и 'type', а' uploads' содержит целочисленный столбец с именем 'mime', который ссылается на' id' в 'mimes' –

+0

Изменено отношение к' return $ this -> hasOne ('App \ Models \ Mime', 'id', 'mime'); 'который исправил ошибку SQL. Хотя проблема в том, что '$ upload-> mime' не является объектом, а просто идентификатором. –

+1

Проверьте @partricus ответ, это именно то, что я бы обновил свой ответ, если он еще не отправил его – haakym

Смежные вопросы