32

私はしばらくの間EloquentORMを使用していて、それをよく知っていますが、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

Laravel 4に移行する予定があるかどうかはわかりませんが、ピボットテーブルフィールドで並べ替えるEloquentの例を次に示します。

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

withPivot雄弁なもののようなもので、ピボットテーブルのフィールドをすでに含まれている他のキーにwith追加します。play_count結果では、すべてのピボットテーブルフィールドに接頭辞が付いてpivotいるため、で直接参照できますorderBy

Laravel 3でどのように表示されるかはわかりませんが、おそらくこれは正しい方向を示すのに役立ちます。

乾杯!

于 2013-06-12T12:35:52.277 に答える
5

ユーザーガイドで何かを見つけました。どうやらあなたはそのwith()方法が必要なようです。

ユーザーガイドから:

デフォルトでは、ピボットテーブルの特定のフィールド(2つの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()で並べ替えられて表示されるのは偶然ではありません。テストを通じてこれを確認しました(単体テストでクエリを表示する方法がまだわからないため)が、おそらくこの動作に依存するべきではありません。ascendingplaycount

于 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

私はこれを(いくつかのビルドで)あなたが持っているように単にリレーションシップメソッドを使用して行ってきました。私はよくピボットテーブルの「order」列を使用してから、このようなことをします。

$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 に答える