web-dev-qa-db-ja.com

EloquentおよびLaravel 5を使用してJSON応答にモデル関係を含める

モデルのセットアップは次のとおりです。

_<?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_は、関連する文字列typeで別のテーブル(_App\Models\Mime_が表す)のIDを参照します。この_92_を上記の文字列に置き換えたいと思います。

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

これはどのように可能ですか? Uploadモデルで_protected $appends_を使っていくつか試しましたが、モデル内からリレーションシップを使用/アクセスする方法を完全に理解しているかどうかはわかりません。

明確化テーブルmimesには列idおよびtypeが含まれますが、テーブルuploadsmimesのIDを参照するmimeという整数列が含まれています

25
Lucas Raines

リレーションシップにテーブルのフィールドの1つと同じ名前を付けることはお勧めできません。これにより、フィールドにアクセスするのではなく、リレーションシップにアクセスしようとするときに問題が発生します(わかっているように)。

理想的には、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に変更されました。アップロードテーブルにはmimesテーブルへの外部キーがあるため、UploadモデルはMimeモデル(およびMimeモデルhasOne/hasMany Uploadモデル)に属します。

これで、コードは次のようになります。

_$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"
}
_
45
patricus

さて、これがあなたが探しているものだと思います...

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

1
haakym