Home > Enterprise >  Laravel 8 Paginate Collection (sortBy)
Laravel 8 Paginate Collection (sortBy)

Time:10-29

I try to paginate a sorted collection in Laravel 8, maybee any one have an idea?

That's my code:

$where = Business::where('name', 'LIKE', '%' . $what . '%');
$businesses = $where->get()->sortByDesc(function($business) {
    return $business->totalReviews;
})->paginate(10); // <--- not working.. Collection::paginate not exists

CodePudding user response:

Remove the get:

$businesses = $where->sortByDesc(function($business) {
    return $business->totalReviews;
})->paginate(10);

CodePudding user response:

Paginate can only be called on a builder instance (it makes no sense to call it on a collection as you already have all the data). But you are doing some logic based on the review count that requires a model method which must can only be called after fetching the data.

So you must refactor the ordering so that it gets called on the builder instance so that the ordering happens on SQL before the pagination logic happens.

withCount('relation') is perfect for this as it will append on a count of a specific relation onto your query which you can then sort by on SQL.

For example you can try this where reviews is a relation on the Business model that you have many of (likely either belongsToMany or hasMany):

Business::withCount('reviews')
   ->where('name', 'LIKE', '%' . $what . '%')
   ->orderBy('reviews_count', 'desc')
   ->paginate(10);

Where inside your Business model you have:

public function reviews()
{
   return $this->hasMany(Review::class);
}

CodePudding user response:

I fixed it on this way

 $businesses = $where->get()->sortByDesc(function($business) {
     return $business->getTotalReviews();
 });

 $businesses = ViewHelper::paginate($businesses, 10);

ViewHelper.class

<?php

    namespace App\Classes;

    use Illuminate\Pagination\LengthAwarePaginator;
    use Illuminate\Pagination\Paginator;
    use Illuminate\Database\Eloquent\Collection;
    
    class ViewHelper
    {
        /**
         * Gera a paginação dos itens de um array ou collection.
        *
        * @param array|Collection      $items
        * @param int   $perPage
        * @param int  $page
        * @param array $options
        *
        * @return LengthAwarePaginator
        */
        public static function paginate($items, $perPage = 15, $page = null, $options = [])
        {
            $page = $page ?: (Paginator::resolveCurrentPage() ?: 1);

            $items = $items instanceof Collection ? $items : Collection::make($items);

            return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
        }
    }
  • Related