使用 Eloquent 和 Laravel 5 在 json 响应中包含模型关系

2022-08-30 13:55:53

我有一个模型设置,如下所示:

<?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"
}

这将引用另一个表(表示)中的 id,并带有与其关联的字符串 。我想用上述字符串替换它。92App\Models\Mimetype92

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

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

澄清mimes 包含列和 ,而表上传包含一个名为的整数列,该列引用 mimes 中的 ididtypemime


答案 1

将关系命名为与表上的某个字段同名不是一个好主意。这会导致在尝试访问关系与访问字段时出现问题(如您所发现的那样)。

理想情况下,您的字段应重命名为 。这符合Laravel的惯例,并且是该领域更准确的名称。mimemime_id

但是,如果您无法更改字段的名称,则应更改关系的名称。

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

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

在上面的类中,关系名称现在是 。此外,关系已从 a 更改为 .由于上传表具有哑剧表的外键,因此上载模型属于哑剧模型(而哑剧模型具有一个/多个上载模型)。uploadMimehasOnebelongsTo

现在,您的代码应如下所示:

$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"
    }
}

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

如果要更接近在问题中提供的 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');
    }
}

这应该会给你一些输出如下内容:

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

通过重写 toArray() 函数来修改 JSON

或者,如果您确实希望 JSON 使用密钥,则可以直接修改该方法:mimetoArray()

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"
}

答案 2

好吧,我相信这就是你要找的...

上传.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');
    }
}

然后你有你的哑剧模型

哑剧.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';

}

如果你这样做是为了测试,我相信你应该看到类型

路线.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


推荐