Laravel Orderprzypisy

Próbuję zdobyć najpopularniejsze hackathony, które wymagają zamówienia przez odpowiednie hackathony partipants->count(). Przepraszam, jeśli to trochę trudne do zrozumienia.

Mam bazę danych w następującym formacie:

hackathons
    id
    name
    ...

hackathon_user
    hackathon_id
    user_id

users
    id
    name

Model Hackathon to:

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');
    }
}

I HackathonParticipant definiuje się jako:

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');
    }
}

Próbowałem Hackathon::orderBy(HackathonParticipant::find($this->id)->count(), 'DESC')->take(5)->get());, ale czuję, że popełniłem duży błąd (prawdopodobnie $this - > id), ponieważ w ogóle nie działa.

Jak mógłbym spróbować dostać najpopularniejsze hackathony, które są oparte na największej liczbie powiązanych hackathonuczestnicy?

Author: Joe Torraca, 2014-06-13

5 answers

Edit: jeśli używasz Laravel 5.2 lub nowszej, użyj odpowiedzi kJamesy. Prawdopodobnie będzie działać nieco lepiej, ponieważ nie będzie musiał ładować wszystkich uczestników i hackathonów do pamięci, tylko paginowane hackathony i liczbę uczestników dla tych hackathonów.

Powinieneś być w stanie użyć Collection'S sortBy() i count() metody, aby zrobić to dość łatwo.

$hackathons = Hackathon::with('participants')->get()->sortBy(function($hackathon)
{
    return $hackathon->participants->count();
});
 41
Author: user1669496,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-17 20:36:48

To działa dla mnie w Laravel 5.3, używając Twojego przykładu:

Hackathon::withCount('participants')->orderBy('participants_count', 'desc')->paginate(10); 

W ten sposób jest uporządkowany na zapytaniu i paginacja działa ładnie.

 185
Author: kJamesy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-13 12:36:53

Innym podejściem może być Metoda withCount().

Hackathon::withCount('participants')
        ->orderBy('participants_count', 'desc')
        ->paginate(50);

Ref: https://laravel.com/docs/5.5/eloquent-relationships#querying-relations

 33
Author: tisuchi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-17 01:19:57

Miałem podobny problem i używanie sortBy() nie jest odpowiednie ze względu na paginację, dokładnie tak, jak Sabrina Gelbart skomentowała w poprzednim rozwiązaniu. Więc użyłem db raw, oto uproszczone zapytanie:

Tag::select( 
array(
    '*',
    DB::raw('(SELECT count(*) FROM link_tag WHERE tag_id = id) as count_links')) 
)->with('links')->orderBy('count_links','desc')->paginate(5);   
 14
Author: Johnyz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-11 16:00:20

Możesz również użyć operatora join. Jak powiedziała Sabrina, nie można używać sortby na poziomie db.

$hackathons = Hackathon::leftJoin('hackathon_user','hackathon.id','=','hackathon_user.hackathon_id')
           ->selectRaw('hackathon.*, count(hackathon_user.hackathon_id) AS `count`')
           ->groupBy('hackathon.id')
           ->orderBy('count','DESC')
           ->paginate(5);

Ale ten kod pobiera wszystkie rekordy z bazy danych. Więc powinieneś paginować ręcznie.

       $hackathons = Hackathon::leftJoin('hackathon_user','hackathon.id','=','hackathon_user.hackathon_id')
           ->selectRaw('hackathon.*, count(hackathon_user.hackathon_id) AS `count`')
           ->groupBy('hackathon.id')
           ->orderBy('count','DESC')
           ->skip(0)->take(5)->get();

Od: https://stackoverflow.com/a/26384024/2186887

 3
Author: Muhammed Tanriverdi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:44