php 使用 Eloquent 和 Laravel 5 在 json 响应中包含模型关系
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30688076/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Include model relationships in json response using Eloquent and Laravel 5
提问by Lucas Raines
I have a Model setup as so:
我有一个模型设置,如下所示:
<?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');
}
}
And when JsonSerialize()
is called, it returns:
当JsonSerialize()
被调用时,它返回:
{
"serverPath": "upload/2015/06/06/21/filename.jpg",
"filename": "filename.jpg",
"mime": "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.
这92
引用了另一个表(App\Models\Mime
表示)中的 id,并带有type
与之关联的字符串。我想92
用上述字符串替换它。
{
"serverPath": "upload/2015/06/06/21/filename.jpg",
"filename": "filename.jpg",
"mime": "image/jpeg"
}
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.
这怎么可能?我protected $appends
在Upload
模型中尝试了一些东西,但我不确定我是否完全理解如何从模型中使用/访问关系。
ClarificationThe table mimescontains columns id
and type
, while table uploadscontains an integer column called mime
that references an id in mimes
澄清表mimes包含列id
and type
,而 table uploads包含一个整数列,称为mime
引用mimes 中的 id
回答by patricus
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.
将关系命名为与表中字段之一相同的名称并不是一个好主意。在尝试访问关系与访问字段时,这会导致问题(如您所见)。
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.
理想情况下,您的mime
字段应重命名为mime_id
. 这符合 Laravel 的约定,是更准确的字段名称。
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');
}
}
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).
在上面的类中,关系名称现在是uploadMime
。此外,关系从 a 更改hasOne
为 a belongsTo
。由于您的uploads 表具有指向mime 表的外键,因此Upload 模型属于Mime 模型(而Mime 模型具有One/hasMany Upload 模型)。
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"
}
}
Modifying JSON using $appends
and attribute accessors
使用$appends
和属性访问器修改 JSON
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:
如果您想更接近您在问题中提供的 JSON 输出,您可以创建一个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');
}
}
This should give you output something along the lines of:
这应该给你输出一些东西:
{
"serverPath": "upload/2015/06/06/21/filename.jpg",
"filename": "filename.jpg",
"mimeType": "image/jpeg"
}
Modifying JSON by overriding the toArray()
function
通过覆盖toArray()
函数修改 JSON
Or, if you really want the JSON to use the mime
key, you can modify the toArray()
method directly:
或者,如果你真的想让 JSON 使用mime
key,你可以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;
}
}
This should give you output something along the lines of:
这应该给你输出一些东西:
{
"serverPath": "upload/2015/06/06/21/filename.jpg",
"filename": "filename.jpg",
"mime": "image/jpeg"
}
回答by haakym
Okay I believe this is what you're looking for ...
好的,我相信这就是你要找的......
Upload.php(no changes here)
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');
}
}
Then you have your Mime model
然后你有你的 Mime 模型
Mime.php
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';
}
if you do this for a test I believe you should see the type
如果你这样做是为了测试,我相信你应该看到类型
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;
});
Check docs for further details on eager loading: http://laravel.com/docs/5.0/eloquent#eager-loading
检查文档以获取有关预先加载的更多详细信息:http: //laravel.com/docs/5.0/eloquent#eager-loading