Laravel 8 集合分页(sortBy)

Laravel 8 Paginate Collection (sortBy)

我尝试对 Laravel 8 中的排序集合进行分页,也许有人有想法吗?

这是我的代码:

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

删除 get:

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

我是这样修复的

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

Paginate 只能在构建器实例上调用(在集合上调用它没有任何意义,因为您已经拥有所有数据)。但是你正在根据评论计数做一些逻辑,需要一个模型方法,该方法必须只能在获取数据后调用。

因此您必须重构排序,以便在构建器实例上调用它,以便在分页逻辑发生之前在 SQL 上进行排序。

withCount('relation') 非常适合此操作,因为它会将特定关系的计数附加到您的查询中,然后您可以根据 SQL.

对其进行排序

例如,您可以试试这个,其中评论是 Business 模型上的一个关系,您有很多(可能是 belongsToManyhasMany):

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

您的 Business 模型中的哪个位置:

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