Laravel OrderBy relationship count

Stefan Izdrail

Founder & Senior Architect · 2026-06-29

Laravel Company
Title: Laravel OrderBy Relationship Count - A Comprehensive Guide for Querying Popular Hackathons Body:

When developing applications using Laravel, it is essential to understand how to query and manage relationships between various models. In this blog post, we will focus on ordering hackathon participants by the number of their respective hackathons, which can be an important aspect when determining popular events. We start with our current database structure and then proceed to write correct queries for this purpose.

Database Structure:

hackathons (Table)
    id
    name
    ...

hackathon_user (Table)
    hackathon_id
    user_id

users (Table)
    id
    name

Model Definitions:

The Hackathon model defines the relationships with users:
class Hackathon extends \Eloquent {
    protected $fillable = ['name', 'begins', 'ends', 'description'];

    protected $table = 'hackathons';

    public function owner()
    {
        return $this->belongsToMany('User', 'hackathon_owner');
    }

    public function participants()
    {
        return $this->belongsToMany('User');
    }

    public function type()
    {
        return $this->belongsToMany('Type');
    }
}
And the HackathonParticipant model defines its relationships with hackathons and users:
class HackathonParticipant extends \Eloquent {

    protected $fillable = ['hackathon_id', 'user_id'];

    protected $table = 'hackathon_user';

    public function user()
    {
        return $this->belongsTo('User', 'user_id');
    }

    public function hackathon()
    {
        return $this->belongsTo('Hackathon', 'hackathon_id');
    }
}

Incorrect Query and Possible Mistakes:

You attempted to use:
Hackathon::orderBy(HackathonParticipant::find($this->id)->count(), 'DESC')->take(5)->get();
Your issue is that you are trying to count the number of participants for a specific hackathon (with given ID) and then order them in descending order by that count. However, it seems like you're using `$this->id` which refers to the current object's identifier instead of the actual hackathon_id used to find hackathons with a specific ID.

Correct Query and Explanation:

To achieve the desired result, we need to follow these steps: 1. Retrieve all HackathonParticipant instances within our given date range (e.g., current day) using `HackathonParticipant::whereBetween('created_at', [start\_date, end\_date])`. 2. If we don't have a specific date range, we can collect all HackathonParticipant instances or use the latest ones (e.g., `HackathonParticipant::latest()->take(5)`). 3. Use the Laravel collection `mapWithKeys()` function to create an associative array that maps each participant instance to its respective hackathon ID and count. Then, sort this new array in descending order by count using the PHP built-in `array_multisort()` function. 4. Iterate through the sorted array and fetch the Hackathon instances with their respective counts without counting duplicates (users participating in multiple hackathons). 5. Lastly, retrieve a subset of hackathons by taking the most popular ones based on the highest count within our desired limit (e.g., 5).
$participants = HackathonParticipant::whereBetween('created_at', [date('Y-m-d'), date('Y-m-d')])
    ->get()
    ->mapWithKeys(function ($hackathonParticipant) {
        return [$hackathonParticipant->hackathon_id => $hackathonParticipant->participants()->count()];
    })
    ->sortByDesc('1')
    ->toArray();

$popularHackathons = Hackathon::with(['owner', 'type'])->whereIn('id', array_keys($participants))
    ->selectRaw('hackathons.*, count(hackathon_participant.user_id) as total_participants')
    ->join('hackathon_participant', function ($join) {
        $join->on('hackathon_participant.hackathon_id', '=', 'hackathons.id')
            ->whereIn('user_id', array_keys($participants))
            ->groupBy('hackathon_participant.hackathon_id');
    })
    ->groupBy('hackathons.id')
    ->orderByDesc('total_participants')
    ->take(5)
    ->get();
This query gives us the most popular hackathons based on the highest number of related participants and ensures that we are ordering by real counts while filtering out duplicated participants. In conclusion, understanding database relationships is crucial to writing efficient queries in Laravel. By following the steps above, you can now correctly order hackathon participants according to their respective hackathon participation counts.