2014-06-13 19 views
17

Sto cercando di ottenere le hackathon più popolari che richiedono l'ordine dal rispettivo hackathon partipants->count(). Scusa se è un po 'difficile da capire.Ordine Laravel Conteggio relazioni

Ho un database con il seguente formato:

hackathons 
    id 
    name 
    ... 

hackathon_user 
    hackathon_id 
    user_id 

users 
    id 
    name 

Il modello Hackathon è:

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

E HackathonParticipant è definito come:

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

ho provato Hackathon::orderBy(HackathonParticipant::find($this->id)->count(), 'DESC')->take(5)->get()); ma mi sento come se avessi fatto un grosso errore (forse il $ this-> id), perché non funziona affatto.

Come dovrei provare a ottenere le hackathon più popolari che si basano sul numero più alto di partecipanti hackathonParticipants?

risposta

21

Dovreste essere in grado di utilizzare i metodi e count() per fare ciò abbastanza facilmente.

$hackathons = Hackathon::with('participants')->get()->sortBy(function($hackathon) 
{ 
    return $hackathon->participants->count(); 
}); 
+0

Come cambiare asending/desecnding? – FooBar

+2

'sortBy (Chiusura $ callback, $ options = SORT_REGULAR, bool $ descending = false)' Basta impostare il 3 ° parametro su true. – user3158900

+19

ordina per non farlo a livello di database ... quindi non funzionerà correttamente con il paging! Buono per quando si restituisce un set completo anche se .. –

12

avevo problema simile e utilizzando sortby() non è adatto a causa di paginazione, esattamente come Sabrina Gelbart commentato in soluzione precedente. così ho usato db grezzo, interrogare qui è semplificato:

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); 
+1

La migliore soluzione che ho trovato per le versioni precedenti di Laravel! (quelli nuovi possono essere usati conCount) Non sono sicuro di cosa fosse ma dovevo fare: 'tag_id = tag.id' invece di' tag_id = id' ... inoltre, puoi semplificarlo ancora di più! Invece di fare 'select' puoi semplicemente eseguire' orderByRaw ('(SELECT count (*) FROM link_tag WHERE tag_id = tag.id) come count_links') DESC ') -> paginate (5) '.E per chi si sta chiedendo, non hai bisogno di '-> with' a meno che tu non stia caricando la relazione –

+0

E ... puoi farlo anche in un ambito se vuoi ...' Tag :: orderByLinkCount() - > paginate (5) 'quindi nel vostro modello Tag create' scopeOrderByLinkCount' con la vostra istruzione OrderByRaw –

+0

Credo che dovrebbe essere 'WHERE tag_id = tag.id' NON' WHERE tag_id = id' –

0

È inoltre possibile utilizzare aderire operatore. Come ha detto Sabrina, non puoi usare sortby a livello 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); 

Ma questo codice prende tutti i record dal database. Quindi dovresti impaginare manualmente.

 $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(); 

Riferito da: https://stackoverflow.com/a/26384024/2186887

36

questo funziona per me in laravel 5.3, con il tuo esempio:

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

In questo modo è ordinato sulla query e l'impaginazione funziona bene.

+0

Questa è una risposta molto migliore di quella accettata uno. – tremby

Problemi correlati