2014-10-15 15 views
7

Sto usando Laravel e MySQL e ho un tavolo post che rappresenta post in cui gli utenti possono commentarlo, ora voglio ordinare post per il numero di commenti di ciascun post in ordine crescente/decrescente ordine, come faccio a farlo a Laravel? Non voglio aggiungere un campo nella tabella post per tenere traccia del numero di commenti di ogni post, perché l'aggiornamento di quel campo manualmente ogni volta che un commento o commento di un commento viene aggiunto/eliminato mi fa impazzire ...Laravel MySQL orderBy count

questo è il modo in creo il mio messaggi tavolo e commenti tavolo:

Schema::create('posts', function($table) { 
    $table->increments('id'); 
    $table->string('title', 100)->unique(); 
    $table->string('content', 2000); 
    $table->timestamps(); 
}); 
Schema::create('comments', function($table) { 
    $table->increments('id'); 
    $table->string('content', 2000); 
    $table->unsignedInteger('post_id'); 
    $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade')->onUpdate('cascade'); 
    $table->unsignedInteger('parent_id')->nullable(); 
    $table->foreign('parent_id')->references('id')->on('comments')->onDelete('cascade')->onUpdate('cascade'); 
    $table->timestamps(); 
}); 

e questo è come mi rapporto di configurazione tra i post e commenti nel mio modello Post:

public function comments() { 
    return $this->hasMany('Comment', 'post_id'); 
} 

E nel Commento modello:

public function post() { 
    return $this->belongsTo('Post', 'post_id'); 
} 

risposta

4

si può fare come hai fatto vedere, ma ora si ottiene tutte le voci dal database. Se avrai 100 post ciascuno con 100 commenti, otterrai 10000 righe dal tuo database solo per ordinare i tuoi post (presumo che tu non voglia visualizzare quei commenti durante l'ordinamento).

Si potrebbe aggiungere al vostro modello Post:

public function commentsCountRelation() 
{ 
    return $this->hasOne('Comment')->selectRaw('post_id, count(*) as count') 
     ->groupBy('post_id'); 
} 

public function getCommentsCountAttribute() 
{ 

    return $this->commentsCountRelation ? 
     $this->commentsCountRelation->count : 0; 
} 

e ora si può usare:

$posts = Post::with('commentsCount')->get()->sortBy(function($post) { 
    return $post->comments_count; 
}); 

per ordine crescente o

$posts = Post::with('commentsCount')->get()->sortBy(function($post) { 
    return $post->comments_count; 
}, SORT_REGULAR, true); 

per ordinare decrescente.

Tra l'altro utilizzando sortBy e poi reverse non è una buona idea si dovrebbe utilizzare i parametri per sortby come ho mostrato

+0

Grazie, posso aggiungere la tua ipotesi, come imposteresti i post DOPO ordinarli usando -> paginate ($ perPage)? – dulan

+0

@dulan Questo potrebbe essere un problema, ma non sono un esperto eloquente. Potresti fare una nuova domanda, forse qualcun altro ha un'altra soluzione o sapere come gestire l'impaginazione in questo caso. La soluzione più semplice sarebbe l'aggiunta di una colonna contatore come hai detto all'inizio e l'aggiunta di un trigger al database per aggiornare questo numero, ma forse ci sono anche altre soluzioni. –

+0

Sto usando gli eventi del modello di Laravel invece dei trigger di database, perché dico che tracciare manualmente il conteggio dei commenti è complicato perché sto usando onDelete ('cascata'), quindi se un commento viene cancellato, tutti i suoi commenti figlio vengono cancellati , quindi devo calcolare quanti commenti-figlio che il commento ha, iterazione, ricorsione e qualunque cosa. Gli eventi del modello si attivano una sola volta per il commento originale che viene eliminato, non si innesca per la cascata ... – dulan

1

Credo è venuta in mente una soluzione:

$posts = Post::with('comments')->get()->sortBy(function($post) { 
    return $post->comments->count(); 
}); 

Questo un ordine per il numero di commenti in modo ascendente, se volete ordinare da essa decrescente, fare questo:

$posts = Post::with('comments')->get()->sortBy(function($post) { 
    return $post->comments->count(); 
})->reverse(); 
+0

questo è impressionante. Mi mancava il() sul mio conteggio, quindi ho modificato il mio commento. –

+0

Non funzionerà se c'è un'impaginazione. – zennin