2014-10-15 18 views
5

Ich habe ein Beiträge Tisch und Kommentare Tisch, Kommentar zu schreiben gehört, und ich habe die Beziehung Setup in Post und Comment-Modell. Ich habe Art durch die Anzahl der Kommentare von jedem Post wie diese Beiträge:Laravel sortBy Paginieren

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

Was ich frage mich, wie ich diese sortiert Beiträge Paginieren können?

funktioniert nicht und gibt mir einen Fehler, der besagt, dass Paginat eine undefinierte Methode ist.

Antwort

4

Ich weiß nicht, ob Sie es Eloquent mit tun können, aber Sie können für diesen Einsatz kommen:

$posts = Post::leftJoin('comments','posts.id','=','comments.post_id')-> 
       selectRaw('posts.*, count(comments.post_id) AS `count`')-> 
       groupBy('posts.id')-> 
       orderBy('count','DESC')-> 
       paginate(20); 

aber es scheint, dass aus diesen paginator in diesem Fall werden alle Datensätze aus der Datenbank genommen werden und nur angezeigt, Wenn Sie also viele Datensätze haben, ist das eine Verschwendung von Ressourcen. Es scheint, Sie sollten dieses Handbuch Paginierung tun:

$posts = Post::leftJoin('comments','posts.id','=','comments.post_id')-> 
       selectRaw('posts.*, count(comments.post_id) AS `count`')-> 
       groupBy('posts.id')-> 
       orderBy('count','DESC')-> 
       skip(0)->take(20)->get(); 

mit skip und take aber ich bin nicht Eloquent Experte und vielleicht ist es eine bessere Lösung, um Ihr Ziel zu erreichen, so dass Sie warten können, und vielleicht wird jemand eine bessere Antwort geben .

+0

Thansk, so dass nur klar sein, wird diese Lösung nicht alle Datensätze aus der Datenbank holen und dann aussortieren, es werden nur 20 Datensätze gleich am Anfang abgerufen? – dulan

+0

@dulan, ja, wenn wir über den zweiten Code sprechen. Im ersten Code alle werden die Datensätze aus der Datenbank erhalten und nur einige von ihnen angezeigt, so dass Sie die zweite Lösung –

+0

dank wählen müssen für überspringen() verwenden –

0

einfach die get() in den verketteten Anrufe entfernen und sehen, was Sie bekommen, Paginieren sollte get() Aufruf ersetzen.

+0

Es wird nicht funktionieren. 'SortBy' für Ergebnismenge verwendet wird, so Paginieren Verwendung macht, dass nur für die ersten 20 Zeilen und nicht für alle Datensätze getan wird die Sortierung. Das ist der Unterschied. Zuerst sortieren dann Paginieren nicht gegenüber –

+0

Ich empfahl ihm die get() zu entfernen, das nicht mit Paginieren() zu ersetzen, ersetzen Paginieren es funktionell zu sprechen. – cdarken

1

Das klingt offensichtlich, aber Eloquent wird ein Ergebnis hier setzt nicht zurück, sondern es wird eine Sammlung zurück.

Wenn Sie in die Quelle graben (Builder::get ruft Builder::getFresh, die Builder::runSelect nennt, die Connection::select nennt), werden Sie feststellen, dass es die Absicht ist, um einfach die Ergebnisse angezeigt werden, die dann in eine Sammlung gelegt (die die sortBy hat Methode).

/** 
* Run a select statement against the database. 
* 
* @param string $query 
* @param array $bindings 
* @param bool $useReadPdo 
* @return array 
*/ 
public function select($query, $bindings = array(), $useReadPdo = true) 
{ 
    return $this->run($query, $bindings, function($me, $query, $bindings) use ($useReadPdo) 
    {  
    if ($me->pretending()) return array(); 

    // For select statements, we'll simply execute the query and return an array 
    // of the database result set. Each element in the array will be a single 
    // row from the database table, and will either be an array or objects. 
    $statement = $this->getPdoForSelect($useReadPdo)->prepare($query); 

    $statement->execute($me->prepareBindings($bindings)); 

    //** this is a very basic form of fetching, it is limited to the PDO consts. 
    return $statement->fetchAll($me->getFetchMode()); 
    }); 
} 

Wenn Sie Paginierung haben wollen, ohne jedes Element geladen wird, dann müssen Sie @ Marcin Lösung verwenden (duplizierte unten):

$posts = Post::leftJoin('comments','posts.id','=','comments.post_id')-> 
      selectRaw('posts.*, count(comments.post_id) AS `count`')-> 
      groupBy('posts.id')-> 
      orderBy('count','DESC')-> 
      skip(0)->take(20)->get();