Rest Laravel:高效检索多态属性

Rest Laravel:高效检索多态属性,rest,laravel,polymorphism,eloquent,Rest,Laravel,Polymorphism,Eloquent,我的实际问题是: 如何将我实际需要的属性返回给客户机,丢弃其余的属性并尽可能高效 所以,我有一个结构,我基本上有媒体对象,可以是不同类型的,像视频,图片,链接等等。这是以多态方式构造的。在这个例子中,用户可以拥有一个虚拟形象,它实际上是一个媒体对象,但在客户端,我唯一感兴趣的是图像url 我们的应用程序是RESTful的,如果我想列出所有用户,我希望用户JSON基本上返回一个属性,其中只有化身的url,而不是完整的多态模型,然后我必须在客户端遍历它,更不用说从服务器发送到客户端的巨大开销了 来自

我的实际问题是: 如何将我实际需要的属性返回给客户机,丢弃其余的属性并尽可能高效

所以,我有一个结构,我基本上有媒体对象,可以是不同类型的,像视频,图片,链接等等。这是以多态方式构造的。在这个例子中,用户可以拥有一个虚拟形象,它实际上是一个媒体对象,但在客户端,我唯一感兴趣的是图像url

我们的应用程序是RESTful的,如果我想列出所有用户,我希望用户JSON基本上返回一个属性,其中只有化身的url,而不是完整的多态模型,然后我必须在客户端遍历它,更不用说从服务器发送到客户端的巨大开销了

来自用户模型:

/**
 * A user can have an avatar
 *
 * @return \Illuminate\Database\Eloquent\Relations\MorphOne
 */
public function avatar() {
    return $this->morphOne('Fanlete\Media', 'appendable');
}
/**
 * A media element can be extended in different ways (kind of inheritance), this function morphs to the specific implementation
 *
 * @return \Illuminate\Database\Eloquent\Relations\MorphTo
 */
public function mediable()
{
    return $this->morphTo();
}

/**
 * A media element can be appended by various models, i.e. a user to save its avatar
 *
 * @return \Illuminate\Database\Eloquent\Relations\MorphTo
 */
public function appendable() {
    return $this->morphTo();
}
public function media()
{
    return $this->morphMany('Fanlete\Media', 'mediable');
}
protected $appends = ['avatar'];

public function getAvatarAttribute()
{
    return $this->avatar()->get()->first()->mediable()->get()->first()->url;
}
来自媒体模型:

/**
 * A user can have an avatar
 *
 * @return \Illuminate\Database\Eloquent\Relations\MorphOne
 */
public function avatar() {
    return $this->morphOne('Fanlete\Media', 'appendable');
}
/**
 * A media element can be extended in different ways (kind of inheritance), this function morphs to the specific implementation
 *
 * @return \Illuminate\Database\Eloquent\Relations\MorphTo
 */
public function mediable()
{
    return $this->morphTo();
}

/**
 * A media element can be appended by various models, i.e. a user to save its avatar
 *
 * @return \Illuminate\Database\Eloquent\Relations\MorphTo
 */
public function appendable() {
    return $this->morphTo();
}
public function media()
{
    return $this->morphMany('Fanlete\Media', 'mediable');
}
protected $appends = ['avatar'];

public function getAvatarAttribute()
{
    return $this->avatar()->get()->first()->mediable()->get()->first()->url;
}
来自图片模型,具体的媒体实现:

/**
 * A user can have an avatar
 *
 * @return \Illuminate\Database\Eloquent\Relations\MorphOne
 */
public function avatar() {
    return $this->morphOne('Fanlete\Media', 'appendable');
}
/**
 * A media element can be extended in different ways (kind of inheritance), this function morphs to the specific implementation
 *
 * @return \Illuminate\Database\Eloquent\Relations\MorphTo
 */
public function mediable()
{
    return $this->morphTo();
}

/**
 * A media element can be appended by various models, i.e. a user to save its avatar
 *
 * @return \Illuminate\Database\Eloquent\Relations\MorphTo
 */
public function appendable() {
    return $this->morphTo();
}
public function media()
{
    return $this->morphMany('Fanlete\Media', 'mediable');
}
protected $appends = ['avatar'];

public function getAvatarAttribute()
{
    return $this->avatar()->get()->first()->mediable()->get()->first()->url;
}
那么,假设我有一个函数来列出控制器中的所有用户:

public function index()
{
    return User::all();

}
$users = Users::with("avatar.mediable")->get()->all();
// Now sort out attributes I don't need and return array
我想要这样的输出:

{
    "id": 1,
    "email": "user@example.org",
    "name": "Example",
    "surname": "User",
    "created_at": "2015-06-17 07:05:26",
    "updated_at": "2015-06-17 07:05:26",
    "avatar": "http://upload.wikimedia.org/wikipedia/en/3/38/Avatarjakeneytiri.jpg"
}
目前,我是这样解决的,这感觉其实并不那么优雅,而且有点错误和瓶颈:

再次选择用户模型:

/**
 * A user can have an avatar
 *
 * @return \Illuminate\Database\Eloquent\Relations\MorphOne
 */
public function avatar() {
    return $this->morphOne('Fanlete\Media', 'appendable');
}
/**
 * A media element can be extended in different ways (kind of inheritance), this function morphs to the specific implementation
 *
 * @return \Illuminate\Database\Eloquent\Relations\MorphTo
 */
public function mediable()
{
    return $this->morphTo();
}

/**
 * A media element can be appended by various models, i.e. a user to save its avatar
 *
 * @return \Illuminate\Database\Eloquent\Relations\MorphTo
 */
public function appendable() {
    return $this->morphTo();
}
public function media()
{
    return $this->morphMany('Fanlete\Media', 'mediable');
}
protected $appends = ['avatar'];

public function getAvatarAttribute()
{
    return $this->avatar()->get()->first()->mediable()->get()->first()->url;
}
当然,我也可以在控制器中执行类似操作:

public function index()
{
    return User::all();

}
$users = Users::with("avatar.mediable")->get()->all();
// Now sort out attributes I don't need and return array
如果没有sortin,输出将如下所示(非常混乱和巨大的开销):

但这也感觉像是一个解决办法,正是我不需要和不想要的开销


thx

你可能就快到了

你的
getAvatarAttribute()
确实太复杂了。您可以尝试执行以下操作:

/** we hide the relation from the json */
protected $hidden = ['avatar'];

/** we append the url of the avatar to the json */
protected $appends = ['avatar_url'];

/**
 * To not be confused with the avatar() method, I used avatar_url.
 */
public function getAvatarUrlAttribute()
{
    return $this->avatar->mediable->url;
}

然后,您应该能够使用('avatar.mediable')->get()执行
$users=User::with('avatar.mediable')没有瓶颈,并且有一个很好的JSON响应。

工作起来很有魅力,甚至可以与其他模型级联!因此,例如,如果一篇博客文章中有用户作为追随者,那么您的解决方案也会将以下用户与avatar_url级联。我必须做一个小小的改变:它是
returnuser::with('avatar.mediable')->get()->all()-注意中间的“get()”。还有一件事:它也适用于just
returnuser::all()-我真的不明白为什么,但似乎laravel在这里为我着想,并自动为我包括所有子模型。@Thinklabs我不确定laravel是否会在没有
with()
的情况下急切地加载化身,这可能会导致性能问题。呵呵,你的速度更快:是的:使用“with”-关键字一可以利用即时加载。所以你的回答很有效率。更多信息可以在这里找到:-如果没有“with”,它也可以工作,但在某些情况下可能会很慢。