使用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引用另一个表(App'Models'Mime表示)中的id,并与一个字符串type相关联。我想用上述字符串替换此92

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

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

说明mimes包含idtype列,而表uploads包含一个名为mime的整数列,该列引用mimes

中的id。

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

理想情况下,应该将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');
    }
}

在上面的类中,关系名称现在是uploadMime。此外,关系从hasOne更改为belongsTo。由于上载表具有Mime表的外键,因此上载模型属于Mime模型(并且Mime模型具有one/hasMany上载模型)。

现在,你的代码应该看起来像:
$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使用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;
    }
}

这应该会输出如下内容:

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

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

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

然后是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';
}

如果你这样做,我相信你应该看到类型

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;
});

查看文档获取更多关于动态加载的详细信息:http://laravel.com/docs/5.0/eloquent#eager-loading