使用Eloquent和Laravel 5在json响应中包括模型关系 [英] Include model relationships in json response using Eloquent and 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
使用与字符串相关联的type
引用另一个表(App\Models\Mime
表示)中的ID.我想用所说的字符串替换这个92
.
This 92
references the id in another table (which App\Models\Mime
represents) with a string, type
, associated with it. I would like to replace this 92
with said string.
{
"serverPath": "upload/2015/06/06/21/filename.jpg",
"filename": "filename.jpg",
"mime": "image/jpeg"
}
这怎么可能?我在Upload
模型中使用protected $appends
尝试了一些东西,但是我不确定我是否完全了解如何从模型内部使用/访问关系.
How is this possible? I tried some stuff with protected $appends
in the Upload
model, but I'm not sure I fully understand how to use/access relationships from within the model.
说明表 mime 包含列id
和type
,而表 uploads 包含一个名为mime
的整数列引用 mime
Clarification The table mimes contains columns id
and type
, while table uploads contains an integer column called mime
that references an id in mimes
推荐答案
将一个关系命名为与表中的字段之一相同的名字不是一个好主意.尝试访问关系与访问字段时,这会导致问题(如您所知).
It is not a good idea to name a relationship the same name as one of the fields on the table. This causes issues (as you've found out) when trying to access the relationship versus accessing the field.
理想情况下,您的mime
字段应重命名为mime_id
.这符合Laravel的约定,并且是该字段的更准确的名称.
Ideally, your mime
field should be renamed to mime_id
. This conforms to Laravel's conventions, and is a more accurate name for the field.
但是,如果您不能更改字段名称,则应该更改关系的名称.
However, if you don't have the ability to change the name of the field, you should change the name of the relationship.
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模型具有One/hasMany Upload模型).
In the class above, the relationship name is now uploadMime
. Additionally, the relationship was changed from a hasOne
to a belongsTo
. Since your uploads table has the foreign key to the mimes table, the Upload model belongsTo the Mime model (and the Mime model hasOne/hasMany Upload models).
现在,您的代码应类似于:
Now, your code should look something like:
$data = \App\Models\Upload::with('uploadMime')->findOrFail(1);
return new JsonResponse($data);
这应该使您可以输出以下内容:
This should give you output something along the lines of:
{
"serverPath": "upload/2015/06/06/21/filename.jpg",
"filename": "filename.jpg",
"mime": "92",
"uploadMime": {
"id": 92,
"type": "image/jpeg"
}
}
使用$appends
和属性访问器修改JSON
Modifying JSON using $appends
and attribute accessors
如果您想进一步了解问题中提供的JSON输出,可以创建mimeType
访问器并将其添加到$appends
属性:
If you wanted to get closer to the JSON output you've provided in your question, you can create a mimeType
accessor and add it to the $appends
property:
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');
}
}
这应该使您可以输出以下内容:
This should give you output something along the lines of:
{
"serverPath": "upload/2015/06/06/21/filename.jpg",
"filename": "filename.jpg",
"mimeType": "image/jpeg"
}
通过覆盖toArray()
函数
Modifying JSON by overriding the toArray()
function
或者,如果您确实希望JSON使用mime
键,则可以直接修改toArray()
方法:
Or, if you really want the JSON to use the mime
key, you can modify the toArray()
method directly:
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;
}
}
这应该使您可以输出以下内容:
This should give you output something along the lines of:
{
"serverPath": "upload/2015/06/06/21/filename.jpg",
"filename": "filename.jpg",
"mime": "image/jpeg"
}
这篇关于使用Eloquent和Laravel 5在json响应中包括模型关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!