32

我已经使用 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");
    }))
4

5 回答 5

52

Not sure if you plan to move to Laravel 4, but here's an Eloquent example for sorting by a pivot tables fields:

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

withPivot is like the eloquent with and will add the play_count field from the pivot table to the other keys it already includes. All the pivot table fields are prefixed with pivot in the results, so you can reference them directly in the orderBy.

I've no idea what it would look like in Laravel 3, but perhaps this will help point you in the right direction.

Cheers!

于 2013-06-12T12:35:52.277 回答
5

我刚刚在用户指南中找到了一些东西,显然您需要该with()方法。

用户指南

默认情况下,只会返回数据透视表中的某些字段(两个 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。我通过测试确认了这一点(因为我还不知道如何在单元测试中显示查询),但您可能不应该依赖这种行为。

于 2013-01-15T20:11:16.257 回答
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();
于 2013-01-13T07:28:54.330 回答
0

我一直在做这个(在几个版本上),只是像你一样使用关系方法。我经常在数据透视表中使用“订单”列,然后执行类似的操作。

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

如果连接表中有名为“order”的列,这可能会不明确。如果是这样,您需要指定 ->order_by( 'article_tag.order' )。是的,您需要使用 ->with() 在结果集中获取该列。就风格而言,我会将 with() 排除在关系方法之外,而只返回普通关系对象。

于 2013-03-30T15:09:54.190 回答
0

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

return $this->belongsToMany('App\Post')->withTimestamps()->orderByDesc('posts.created_at');
于 2017-09-26T14:34:36.460 回答