sdexp
sdexp

Reputation: 776

Laravel: Ordering data at a query level when using pivot tables?

In my routes/web.php I have a route like this...

Route::get('/tags/{tag}', 'TagsController@show');

Then, inside TagsController because I have a post_tag pivot table that has been defined as a many-to-many relationship.

Tag.php...

public function posts(){
    return $this->belongsToMany(Post::class);
}

public function getRouteKeyName(){
  return 'name';
}

Post.php...

public function tags(){
    return $this->belongsToMany(Tag::class);
}

I get the posts for a certain tag like this...

public function show(Tag $tag){
    $posts = $tag->posts;
    return view('posts.index', compact('posts','tag'));
}

Then, to sort the posts into newest first I can do this in index.blade.php...

      @foreach ($posts->sortByDesc('created_at') as $post)
         @include('posts.post')
      @endforeach

This works fine, but I'm doing the re-ordering at collection level when I'd prefer to do it at query level.

From Eloquent: Relationships I can see that I can do something like this, which also works...

$user = App\User::find(1);
foreach ($user->roles as $role) {
    //
}

But, something like this does not seem to work...

public function show($tag){
    $posts = \App\Tag::find($tag);
    return view('posts.index', compact('posts'));
}

My question is, how can I filter/order the data at a query level when using pivot tables?

Upvotes: 0

Views: 210

Answers (2)

Max Gaurav
Max Gaurav

Reputation: 1913

Extending @leli. 1337 answer

To order content without changing the relation created.

First, keep the original relation

class User 
{ 
    public function tags
    {
       return $this->belongsToMany(Tag::class);
    }
}

Second, during query building do the following

//say you are doing query building

$users = User::with([
    'tags' => function($query) {
         $query->orderBy('tags.created_at','desc');
    }
])->get();

With this, you can order the content of tags data and in query level also if needed you can add more where clauses to the tags table query builder.

Upvotes: 1

Zenel Rrushi
Zenel Rrushi

Reputation: 2366

To order your collection you must change

public function tags(){
    return $this->belongsToMany(Tag::class);
}

to

public function tags(){
    return $this->belongsToMany(Tag::class)->orderBy('created_at');
}

Upvotes: 2

Related Questions