2014-10-15 3 views
7

Ich benutze Laravel und MySQL, und ich habe eine Tabelle post, die Post darstellt, wo Benutzer kommentieren können, jetzt möchte ich Beiträge nach der Anzahl der Kommentare von jedem Beitrag in aufsteigender/absteigender Reihenfolge Bestellung, wie mache ich das in Laravel? Ich möchte kein Feld in Beitrag Tabelle hinzufügen, um die Anzahl der Kommentare jedes Beitrags zu verfolgen, da das Feld jedes Mal manuell aktualisieren, wenn ein Kommentar oder ein Kommentar hinzugefügt/gelöscht wird, macht mich verrückt ...Laravel MySQL orderBy zählen

Dies ist, wie ich meine Beiträge Tabelle erstellen und Kommentare Tabelle:

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

und das ist, wie ich ein Setup Beziehung zwischen Beiträgen und Kommentaren in meinem Beitrag Modell:

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

Und in Kommentar Modell:

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

Antwort

4

Sie können das tun, wie Sie gezeigt haben, aber jetzt erhalten Sie alle Einträge aus der Datenbank. Wenn Sie 100 Beiträge mit jeweils 100 Kommentaren haben, erhalten Sie 10000 Zeilen von Ihrer Datenbank, nur um Ihre Beiträge zu sortieren (ich nehme an, dass Sie diese Kommentare beim Sortieren nicht anzeigen wollen).

könnten Sie zu Ihrem Beitrag Modell hinzufügen:

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

und jetzt können Sie verwenden:

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

aufsteigend zu sortieren oder

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

absteigend zu sortieren.

Durch die Art und Weise sortBy und später reverse verwendet, ist keine gute Idee, Sie Parameter sortBy verwenden sollten, wie ich

zeigte
+0

Danke, darf ich in Ihrer Annahme hinzufügen, wie würden Sie Posts paginieren, nachdem Sie sie mit -> paginate ($ perPage) sortiert haben? – dulan

+0

@dulan Das könnte ein Problem sein, aber ich bin kein beredter Experte. Sie könnten eine neue Frage stellen, vielleicht hat jemand anderes eine andere Lösung oder kann in diesem Fall mit der Paginierung umgehen. Die einfachste Lösung wäre, die Zählerspalte wie eingangs erwähnt hinzuzufügen und der Datenbank einen Trigger hinzuzufügen, um diese Zahl zu aktualisieren, aber vielleicht gibt es auch andere Lösungen. –

+0

Ich benutze Laravel-Modell-Ereignisse anstelle von Datenbank-Triggern, warum ich sage, die Zählung der Kommentare manuell zu verfolgen ist kompliziert, weil ich onDelete ('cascade') verwende, also wenn ein Kommentar gelöscht wird, wurden alle seine untergeordneten Kommentare gelöscht , dann muss ich berechnen, wie viele Kinderkommentare der Kommentar hat, Iteration, Rekursion und was auch immer. Die Modell-Ereignisse werden nur einmal für den ursprünglichen Kommentar ausgelöst, der gelöscht wird. Bei Kaskaden wird er nicht ausgelöst. – dulan

1

Ich glaube, ich mit einer Vermeidung des Problems habe kommen:

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

Dieser Auftrag durch die Anzahl der Kommentare aufsteigend, wenn Sie wollen, indem sie es bestellen absteigend, tun Sie dies:

+0

Das ist fantastisch. Mir fehlte das() in meiner Rechnung, also habe ich meinen Kommentar bearbeitet. –

+0

Es funktioniert nicht, wenn eine Seitennummerierung vorhanden ist. – zennin