Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jonaspas's avatar

Order by pivot table field

Hi there! Couldn't find an answer for this one, even after longer searching: I want to order a list of items by the date of an "event" (event like "birthday", "wedding" and so on, not like an event in a programming language). An item can have multiple events, but I want the items to be ordered by the event that happens next. Simplified, I would really like to do in my ItemsController something like:

$items = Item::with('nearest_event')->orderBy('nearest_event')->get();

So I tried to add this to my Item model:

public function nearest_event()
    {
        return $this->belongsToMany('App\Event')->orderBy('date')->first();
    }

It seems that it isn't possible like this, I get this error: "Call to undefined method Illuminate\Database\Query\Builder::addEagerConstraints()" Is there a way to get only the first result from a many-to-many-relation? Maybe my thinking how to do this is totally wrong and someone can help me cut the knot in my head ^^ Thanks in advance! Jonas

0 likes
6 replies
gabrielbuzzi's avatar
public function events () {
    return $this->belongsToMany(Event::class)->orderBy('date', 'desc');
}

public function next_event() {
    return $this->events()->first();
}
1 like
jonaspas's avatar

Thank you for your answer! But unfortunately I still get the same error when I'm doing it like that. Maybe something wrong in my code elsewhere? Don't know if this is important: I'm on Laravel 5.2.36 currently.

willvincent's avatar

Aside from the constraint issue, it seems to me you also need a where condition because if you just order by date ascending or descending, you'll just get the first item or last item in the list, not the 'next' upcoming event... which seems like it would be the most beneficial thing to retrieve. So you'd need a condition that says give me the first date that is greater than or equal to today.

The constraints though, need to be separate from the relationship. Try something like this:

public function events() {
  return $this->belongsToMany(Event::class);
}

public function next_event() {
  return $this->events()
    ->where('date', '>=', Carbon::now()->startOfDay())
    ->orderBy('date', 'asc')
    ->first();
}

That ought to work.

1 like
TiborBesze's avatar

I'd use local query scopes for this, that would give you better control over your data.

public function events()
{
    return $this->belongsToMany(Event::class);
}

public function scopeFutureEvents($query)
{
    return $query->where('date', '>', Carbon::today())->orderBy('date', 'DESC');
}

public function nextEvent()
{
    return $this->futureEvents()->first();
}
1 like
jonaspas's avatar

Thank you all very much! Yes, @willvincent, you are absolutely right, I need to make a query as you told. I wasn't that far in my thinking ;)

I tried all the solutions ( I guess local scope is something I have to read about a little more in the docs to understand it completely ;) ) But I still have the error message:

BadMethodCallException in Builder.php line 2345:
Call to undefined method Illuminate\Database\Query\Builder::addEagerConstraints()

In my controller I try to get the items like this:

$articles = Item::with('next_event')->get();

I guess there's an error in this line?

FERN's avatar

For those who come from Google like myself, I finally found a way to make it work, you need to use dot notation with the name of the pivot table and the column you want:

        ->belongsToMany('App\Event')
        ->withPivot('my_pivot_column') // also show a custom pivot column
        ->orderBy('event_item.my_pivot_column'); // the column to order
1 like

Please or to participate in this conversation.