Laravel 如何在雄辩的ORM中按多对多关系的透视表字段排序

Laravel 如何在雄辩的ORM中按多对多关系的透视表字段排序,laravel,eloquent,Laravel,Eloquent,我已经使用雄辩的ORM有一段时间了,我非常了解它,但我不能做以下事情,而用流利的很容易做到 我有很多歌曲的用户,中间表是song_用户(应该是这样)。根据播放次数,我想获得用户的热门歌曲。当然,播放计数存储在中间表中 我可以流利地说: $songs = DB::table('songs') ->join('song_user', 'songs.id', '=', 'song_user.song_id') ->where('song_user.user_id', '='

我已经使用雄辩的ORM有一段时间了,我非常了解它,但我不能做以下事情,而用流利的很容易做到

我有很多歌曲的用户,中间表是song_用户(应该是这样)。根据播放次数,我想获得用户的热门歌曲。当然,播放计数存储在中间表中

我可以流利地说:

$songs = DB::table('songs')
    ->join('song_user', 'songs.id', '=', 'song_user.song_id')
    ->where('song_user.user_id', '=', $user->id)
    ->orderBy("song_user.play_count", "desc")
    ->get();
简单。但我想用雄辩的语言来表达,当然这是行不通的:

$songs = Song::
    with(array("song_user" => function($query) use ($user) {
        $query->where("user_id", "=", $user->id)->orderBy("play_count", "desc");
    }))

任何可以用流利的语言表达的方法也可以用雄辩的语言表达。也许这就是你要找的

$songs = Song->join('song_user', 'songs.id', '=', 'song_user.song_id')
->where('song_user.user_id', '=', $user->id)
->orderBy("song_user.play_count", "desc")
->get();

我刚刚在用户指南中找到了一些东西,显然你需要这个方法

从:

默认情况下,只返回透视表中的某些字段 (两个id字段和时间戳)。如果数据透视表包含 此外,还可以使用with()方法获取其他列 :

类用户扩展了雄辩的{
公共职能角色()
{
return$this->has_many_和_归属于('Role','user_roles')->with('column');
}
}
因此,在定义关系时,您可以使用类似的方法:

$this->has_many__和_归属于('User')->with('playcount');
例子 我只是用这个来确保它能正常工作

班歌演绎雄辩{
函数用户()
{
return$this->has_many_和_归属于('User')->with('playcount');
}
}
类用户扩展了雄辩的{
功能歌曲()
{
return$this->has_many_和_归属于('Song')->with('playcount');
}
}
//我的测试方法
类TestOrm扩展了PHPUnit\u框架\u测试用例{
公共函数testSomethingIsTrue()
{
foreach(用户::find(3)->songs()->order_by('playcount')->get()作为$song)
echo$song->name':',$song->pivot->playcount,“\n”;
回音“\n”;
foreach(User::find(3)->songs()->order_by('playcount','desc')->get()作为$song)
echo$song->name':',$song->pivot->playcount,“\n”;
}
}
输出 注意:如果不使用
order\u by()
,结果将按
播放次数的
升序排序,这并非巧合。我通过测试确认了这一点(因为我还不知道如何在单元测试中显示查询),但您可能不应该依赖于这种行为。

我(在多个构建中)只是像您一样使用关系方法。我经常在透视表中使用“order”列,然后执行类似的操作

$article->tags()->order_by( 'order')->get();

如果联接表中有名为“order”的列,则这可能不明确。如果是这样,您需要指定->order\u by('article\u tag.order')。是的,您需要使用->with()在结果集中获取该列。作为一个风格问题,我将把with()从relationship方法中去掉,只返回vanilla relationship对象。

不确定是否计划移动到Laravel 4,但下面是一个按透视表字段排序的雄辩示例:

public function songs() {
  return $this
    ->belongsToMany('Song')
    ->withPivot('play_count')
    ->orderBy('pivot_play_count', 'desc');
}
withPivot
类似于雄辩的
with
,它将把透视表中的
play\u count
字段添加到它已经包含的其他键中。所有数据透视表字段在结果中都以
pivot
作为前缀,因此您可以在
orderBy
中直接引用它们

我不知道它会是什么样子在拉威尔3,但也许这将帮助你在正确的方向


干杯

在雄辩的模型中,如果包含表名,则可以链接orderBy列:

return $this->belongsToMany('App\Post')->withTimestamps()->orderByDesc('posts.created_at');

不,我正在寻找一种更雄辩的方法,看看我的例子,它不起作用。我发布的答案确实很雄辩。它将返回一个属于用户并通过play_count字段(从联接表)排序的雄辩对象数组(在本例中为歌曲)。这也可以直接从用户对象中完成,您试图查找其歌曲$user->songs()->order\u by('play\u count','asc')->get()。您失败的示例毫无意义:急切地加载song_用户数据透视表与创建联接不同,在本例中,您没有理由急切地加载。一个简单的连接应该可以满足您的需要。我没有设置来尝试它,但是您是否尝试过类似于
$songs=$usr->songs()->pivot()->order_by('play_count','desc')->songs()的方法?问题是你是否可以在透视表之后“返回”到
歌曲
,因为它似乎不是一个正常的模型。不幸的是,这不起作用。你总是可以使透视表成为一个模型并完成它。您只需设置额外的外键,以便在其各自的父项被删除时正确删除条目。我目前正在这样做,但使用这种方法,您将失去对仅限用户的歌曲($user->songs())的自动筛选,并且您必须记住手动执行(
SongUser::where(“user_id”),“=”,$user->id)->等等。
)。为什么,这是关系的目的,而不是与透视表建立一对多的二对一关系。您只需添加一些类似于
$this->has\u many('song\u user')
的内容,我不知道我可以像那样在模型中添加orderBy。你至少应该得到+1!请指出文档中提到的pivot字段前缀是否适用于Laravel 5.2,而无需为pivot表字段添加前缀
return $this->belongsToMany('App\Post')->withTimestamps()->orderByDesc('posts.created_at');