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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 22:00:11  来源:igfitidea点击:

Include model relationships in json response using Eloquent and Laravel 5

phplaraveleloquentlaravel-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 92references the id in another table (which App\Models\Mimerepresents) with a string, type, associated with it. I would like to replace this 92with 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 $appendsin the Uploadmodel, but I'm not sure I fully understand how to use/access relationships from within the model.

这怎么可能?我protected $appendsUpload模型中尝试了一些东西,但我不确定我是否完全理解如何从模型中使用/访问关系。

ClarificationThe table mimescontains columns idand type, while table uploadscontains an integer column called mimethat references an id in mimes

澄清mimes包含列idand 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 mimefield 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 hasOneto 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 $appendsand attribute accessors

使用$appends和属性访问器修改 JSON

If you wanted to get closer to the JSON output you've provided in your question, you can create a mimeTypeaccessor and add it to the $appendsproperty:

如果您想更接近您在问题中提供的 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 mimekey, you can modify the toArray()method directly:

或者,如果你真的想让 JSON 使用mimekey,你可以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