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

Luc*_*nes 27 php laravel eloquent 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');
    }
}
Run Code Online (Sandbox Code Playgroud)

JsonSerialize()被调用时,它返回:

{
    "serverPath": "upload/2015/06/06/21/filename.jpg",
    "filename": "filename.jpg",
    "mime": "92"
}
Run Code Online (Sandbox Code Playgroud)

92引用了另一个表(App\Models\Mime表示)中的id 和一个type与之关联的字符串.我想92用所述字符串替换它.

{
    "serverPath": "upload/2015/06/06/21/filename.jpg",
    "filename": "filename.jpg",
    "mime": "image/jpeg"
}
Run Code Online (Sandbox Code Playgroud)

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

澄清该表哑剧包含列idtype,而表上传包含称为整数列mime,在引用了ID 默剧

pat*_*cus 47

将关系命名为与表中某个字段相同的名称并不是一个好主意.在尝试访问关系与访问字段时,这会导致问题(正如您所知).

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

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

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

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

在上面的类中,关系名称现在是uploadMime.此外,关系从a hasOne变为a belongsTo.由于您的上传表具有mimes表的外键,因此上传模型属于Mime模型(并且Mime模型具有One/hasMany上载模型).

现在,您的代码应该类似于:

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

这应该给你输出的东西:

{
    "serverPath": "upload/2015/06/06/21/filename.jpg",
    "filename": "filename.jpg",
    "mime": "92",
    "uploadMime": {
        "id": 92,
        "type": "image/jpeg"
    }
}
Run Code Online (Sandbox Code Playgroud)

使用$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');
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该给你输出的东西:

{
    "serverPath": "upload/2015/06/06/21/filename.jpg",
    "filename": "filename.jpg",
    "mimeType": "image/jpeg"
}
Run Code Online (Sandbox Code Playgroud)

通过覆盖toArray()函数来修改JSON

或者,如果您确实希望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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该给你输出的东西:

{
    "serverPath": "upload/2015/06/06/21/filename.jpg",
    "filename": "filename.jpg",
    "mime": "image/jpeg"
}
Run Code Online (Sandbox Code Playgroud)