简体   繁体   中英

Laravel 5.3 pagination on sortBy collection

Why the paginate method doesn't work on this example ?

$shopIds = Follower::whereUserId($user->id)->orderBy('created_at','desc')->get()->pluck('shop_id')->toArray();
            $shops = Shop::whereIn('id',$shopIds)->with('deals')->with('deals.likes')->paginate($this->perPage)->sortBy(function($likes) {
                return $likes->count();
            });
            dd($shops);

在此处输入图片说明

Thank's for help ;)

The paginate is just working fine but the sortBy method is creating the problem for you because when you use sortBy it returns a new collection.

So finally your $shops is an instance of Illuminate\\Support\\Collection not of Illuminate\\Pagination\\LengthAwarePaginator .

You can try it as:

$paginated_shops = Shop::whereIn('id',$shopIds)
                  ->with('deals')
                  ->with('deals.likes')
                  ->paginate($this->perPage);

$shops = $paginated_shops->sortBy(function($likes) {
        return $likes->count();
    });

$shops = new LengthAwarePaginator($shops, $paginated_shops->total(), $paginated_shops->perPage());

Remember to add use statement at the top of the class as:

use Illuminate\Pagination\LengthAwarePaginator;

Thank you guys!

I fix it like that

$shopIds = Follower::whereUserId($user->id)->orderBy('created_at','desc')->get()->pluck('shop_id')->toArray();
            $shopIds = Shop::whereIn('id',$shopIds)->with('deals')->with('deals.likes')->get()->sortBy(function($likes) {
                return $likes->count();
            })->pluck('id')->toArray();
            $orderedIds = implode(',',$shopIds);
            $shops = Shop::whereIn('id', $shopIds)->whereNotIn('user_id', [$user->id])->orderByRaw(\DB::raw("FIELD(id, ".$orderedIds." )"))->paginate($this->perPage);
            dd($shops);

and now I have an instance of Illuminate\\Pagination\\LengthAwarePaginator在此处输入图片说明

Thank's

Like @Amit mentionned, $shops is a collection, thus not a LengthAwarePaginator. You are going to have to build the paginator and slice it yourself... not too complicated...

For example, let's assume you are hitting your route, calling your controller... then returning results to a view... Now that route is going to get requested with the pagination info in the request, you job is to get the result $shops into an array, slice the array into the right result for the page and return that to your view... I have not run this code... so take this as an example... but it will look something like:

public function yourController{

    // This will return a collection... we will convert it to array later
    $shops = Shop::whereIn('id',$shopIds)->with('deals')->with('deals.likes')->paginate($this->perPage)->sortBy(function($likes) {
            return $likes->count();
        });

    $shopsArray = $shops->toArray();

    // Here we deal with the slicing... you need to slice the page you are
    // at the paging info is in the request... 

    // this basically gets the request's page variable... or defaults to 1
    $page = Paginator::resolveCurrentPage('page') ?: 1;

    // Assume 15 items per page... so start index to slice our array
    $startIndex = ($page - 1) * 15;

    // Length aware paginator needs a total count of items... to paginate properly
    $total = count($shopsArray);

    // Eliminate the non relevant items by slicing the array to page content...
    $results = array_slice($shopsArray, $startIndex, 15);

    $result =  new LengthAwarePaginator($results, $total, 15, $page, [
        'path' => Paginator::resolveCurrentPath(),
        'pageName' => 'page',
    ]);
    return view('yourView', compact('result'));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM