我一直在使用Eloquent ORM已经有一段时间了,我知道它很好,但是我不能做到以下几点,而在Fluent中很容易做到。
我的用户有多对多的歌曲,中间表是song_user(就像它应该的那样)。根据播放次数判断,我想获得用户的热门歌曲。当然,播放计数存储在中间表中。
我可以在Fluent中完成:
$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();
易。但我想在Eloquent中做到这一点,当然不起作用
$songs = Song::
with(array("song_user" => function($query) use ($user) {
$query->where("user_id", "=", $user->id)->orderBy("play_count", "desc");
}))
答案 0 :(得分:49)
不确定您是否计划迁移到Laravel 4,但这是一个根据数据透视表字段排序的雄辩示例:
public function songs() {
return $this
->belongsToMany('Song')
->withPivot('play_count')
->orderBy('pivot_play_count', 'desc');
}
withPivot
就像雄辩的with
一样,会将数据透视表中的play_count
字段添加到已包含的其他键中。所有数据透视表字段都在结果中以pivot
为前缀,因此您可以直接在orderBy
中引用它们。
我不知道它在Laravel 3中会是什么样子,但也许这会帮助你找到正确的方向。
干杯!
答案 1 :(得分:5)
我刚刚在用户指南中找到了一些内容,显然您需要with()
方法。
来自User-Guide:
默认情况下,仅返回数据透视表中的某些字段 (两个id字段和时间戳)。如果您的数据透视表包含 在其他列中,您也可以使用with()方法获取它们 :
class User extends Eloquent { public function roles() { return $this->has_many_and_belongs_to('Role', 'user_roles')->with('column'); } }
因此,在定义关系时,您可以使用与此相似的内容:
$this->has_many_and_belongs_to('User')->with('playcount');
我只是用它来确保它有效......
class Song extends Eloquent {
function users()
{
return $this->has_many_and_belongs_to('User')->with('playcount');
}
}
class User extends Eloquent {
function songs()
{
return $this->has_many_and_belongs_to('Song')->with('playcount');
}
}
// My test method
class TestOrm extends PHPUnit_Framework_TestCase {
public function testSomethingIsTrue()
{
foreach(User::find(3)->songs()->order_by('playcount')->get() as $song)
echo $song->name, ': ', $song->pivot->playcount, "\n";
echo "\n";
foreach(User::find(3)->songs()->order_by('playcount','desc')->get() as $song)
echo $song->name, ': ', $song->pivot->playcount, "\n";
}
}
Jingle Bells: 5
Mary had a little lamb: 10
Soft Kitty: 20
The Catalyst: 100
The Catalyst: 100
Soft Kitty: 20
Mary had a little lamb: 10
Jingle Bells: 5
注意:如果不使用order_by()
,ascending
按playcount
顺序显示结果,则绝非巧合。我通过测试证实了这一点(因为我还不知道如何在单元测试中显示查询),但你可能不应该依赖这种行为。
答案 2 :(得分:1)
Fluent中提供的任何方法也应该与Eloquent一起提供。也许这就是你要找的东西?
$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();
答案 3 :(得分:0)
我一直在使用关系方法(在几个版本中)这样做。我经常在数据透视表中使用“订单”列,然后执行类似的操作。
$article->tags()->order_by( 'order')->get();
如果在连接表中有名为“order”的列,则这可能不明确。如果是这样,您需要指定 - > order_by('article_tag.order')。是的,您需要使用 - > with()来获取结果集中的该列。作为样式的问题,我会将with()从关系方法中删除,而只是返回vanilla关系对象。
答案 4 :(得分:0)
在您的Eloquent模型中,如果包含表名,则可以链接orderBy列:
return $this->belongsToMany('App\Post')->withTimestamps()->orderByDesc('posts.created_at');