如何按Eloquent ORM中多对多关系的数据透视表的字段进行排序

dua*_*ty_ 30 laravel eloquent

我一直在使用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();
Run Code Online (Sandbox Code Playgroud)

简单.但我想在Eloquent中做到这一点,当然这不起作用:

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

Big*_*Hat 49

不确定您是否计划迁移到Laravel 4,但这是一个根据数据透视表字段排序的雄辩示例:

public function songs() {
  return $this
    ->belongsToMany('Song')
    ->withPivot('play_count')
    ->orderBy('pivot_play_count', 'desc');
}
Run Code Online (Sandbox Code Playgroud)

withPivot就像雄辩一样with,它会将play_count数据透视表中的字段添加到已包含的其他键中.所有数据透视表字段都以pivot结果为前缀,因此您可以直接在其中引用它们orderBy.

我不知道它在Laravel 3中会是什么样子,但也许这会帮助你指明正确的方向.

干杯!

  • 我不知道我能在这样的模型中坚持orderBy.你应该得到至少+1! (3认同)

dua*_*led 5

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

来自用户指南:

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

class User extends Eloquent {
  public function roles()
  {
    return $this->has_many_and_belongs_to('Role', 'user_roles')->with('column');
  }
}
Run Code Online (Sandbox Code Playgroud)

因此,在定义关系时,您可以使用与此类似的内容:

$this->has_many_and_belongs_to('User')->with('playcount');
Run Code Online (Sandbox Code Playgroud)

我只是用它来确保它有效......

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";
    }
}
Run Code Online (Sandbox Code Playgroud)

产量

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
Run Code Online (Sandbox Code Playgroud)

注意:不使用order_by()结果显示按ascending顺序排序并非巧合playcount.我通过测试证实了这一点(因为我还不知道如何在单元测试中显示查询),但你可能不应该依赖这种行为.