2014-10-15 5 views
5

У меня есть сообщений стол и комментарии стол, комментарий принадлежит сообщению, и у меня есть настройка отношений в модели Post и Comment. Я сортировать должности по количеству комментариев каждого поста, как это:Laravel sortBy paginate

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

Что интересно, как я могу постраничный эти упорядоченные сообщения?

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

не работает и дает мне сообщение об ошибке, указывающее, что paginate является неопределенным методом.

ответ

4

Я не знаю, если вы можете сделать это с помощью красноречивых, но вы можете использовать присоединиться к этим:

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

Однако, кажется, что в этом случае все записи взяты из базы данных и отображаются только те из постраничной навигации , поэтому, если у вас много записей, это пустая трата ресурсов. Кажется, что вы должны сделать вручную пагинации для этого:

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

использованием skip и take, но я не Eloquent экспертом и может быть, есть лучшее решение, чтобы достичь своей цели, так что вы можете ждать, и, возможно, кто-то даст лучший ответ ,

+0

Thansk, так просто чтобы быть ясно, это решение не будет извлекать все записи из базы данных и затем сортировать их, он извлекает только 20 записей в самом начале права? – dulan

+0

@дулан, да, если мы говорим о втором коде. В первом коде все записи будут поступать из базы данных и отображать только некоторые из них, поэтому вам нужно выбрать второе решение –

+0

спасибо за использование skip() –

0

Просто удалите get() в цепных вызовах и посмотрите, что вы получаете, paginate должен заменить вызов get().

+0

Это не сработает. 'sortBy' используется для набора результатов, поэтому с помощью paginate эта сортировка будет выполняться только для первых 20 строк, а не для всех записей. В этом разница. Сначала сортируйте, а затем paginate не противоположно –

+0

Я рекомендовал ему удалить get(), а не заменять его paginate(), paginate заменит его функционально. – cdarken

1

Это звучит очевидно, но Eloquent не вернет результат здесь, а вернет коллекцию.

Если покопаться в источнике (Builder::get называет Builder::getFresh, которая вызывает Builder::runSelect, который называет Connection::select), вы обнаружите, что это намерение просто вернуть результаты, которые затем помещаются в коллекцию (которая имеет SortBy метод).

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

Если вы хотите иметь нумерацию страниц без загрузки каждого пункта, то вам нужно использовать @ решение Marcin в (дублируется ниже):

$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(); 
Смежные вопросы