如何 paginate 分页后, 根据指定循环组装的 字段 进行排序,且保持分页效果?

$companies = $builder->paginate();

        foreach ($companies as $company) {
            // 注册人数
            $company['register_count'] = User::query()->where('company_id', $company->id)->count();
            // 培训人数
            $company['train_count']    = CourseLearnRecord::query()->where('company_id', $company->id)
                ->groupBy('user_id')->get(['user_id'])->count();
            // 考核人数
            $company['check_count']    = UserExam::query()->where('company_id',
                $company->id)->whereNull('spot_check_id')
                ->groupBy('user_id')->get(['user_id'])->count();
        }

现在想 根据 循环组装的register_count 排序, 且保持分页的效果。

paginate() 分页后, $companies->sortByDesc(‘register_count’)->values() , sortByDesc 似乎没有效果, 且分页数据丢失。

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 13

这种,用collect函数再排一次本页的顺序

2年前 评论

@deatil 首先查询的公司表数据太大,70万数据, 不用paginate()去查询组装数据的话, 会非常的慢, paginate() 后使用 sortByDesc 无效

2年前 评论

collect($companies->item())->map()->sortByDesc()

2年前 评论

不使用 分页函数 自己写

User::query()
  ->offset(($paggNum - 1) * $pageSize )
  ->limit($pageSize)
  ->get()
  ->map(function($item){
     return [ 
    //需要什么字段返回什么     
    'myName'=>$item->name,
    'myAge'=>$item->age
    ]
  })
  ->orderBy('myAge');
2年前 评论
gyp719 (楼主) 2年前
风吹过有夏天的味道 (作者) 2年前
chowjiawei

看的很累,用这个包吧

use Spatie\QueryBuilder\QueryBuilder;
use Spatie\QueryBuilder\AllowedFilter;
use Spatie\QueryBuilder\AllowedSort;

file

2年前 评论
Complicated

兄弟,我感觉你这么写,且不说排序的问题,就这循环查询也不太好啊。如果可以的话,还是多存个字段吧。如果不能加字段,一楼二楼的方案应该可以

2年前 评论

$builder->withCount(''register)->orderByDesc('register_count') 这样?

2年前 评论
Complicated

@hogus2037 他用的不是关联查询,所以用不了withCount()

2年前 评论

两个方案:

  1. 使用获取分页中的集合,遍历处理后再放回去
    $paginate = $query->paginate(15);
    $items = $paginate->getCollection();
    $items = $items->map(function($item) {
    // 处理逻辑
    })->sortByDesc('register_count')->all();
    $paginate->setCollection($items)
    return response()->json($paginate);
  2. 自己实现分页的逻辑,处理完后再构造分页器
    $size = (integer)$request->get('size', 15);
    $page = $request->get('page', 1);
    $offset = $page * $size - $size;
    $query = Model::query();
    $total = $query->count();
    $items = $query->skip($offset)
       ->orderBy('created_at', 'desc')
       ->take($size)
       ->get()->map(function($item) {
             // 处理逻辑
       })->sortByDesc('register_count')->all();
    $pageinate = new LengthAwarePaginator($items, $total, $size, $page, [
       'path' => Paginator::resolveCurrentPath(),
       'pageName' => 'page',
    ]);
2年前 评论
gyp719 (楼主) 2年前
GeorgeKing (作者) 2年前

如果只想给当前页面的数据排序,那可以在获取后排序

否则,应该join起来,然后根据统计出来的数据用order by排序

2年前 评论

9楼哥们的方案一的思路是对的,代码的话大致可以参考这一段:

    $data = $repo->paginate();
    foreach ($data as $item) {
        $item['sort'] = mt_rand(0, 10);
    }
    $data->setCollection($data->sortByDesc('sort')->values());
    return $data;
2年前 评论

根据上面兄弟的一些建议和方法, 目前是这样来实现的, 但是查询的比较慢

$street_id    = $request->input('street_id');
        $level        = $request->input('level');
        $company_name = $request->input('company_name');
        $type         = $request->input('type', 'register_count');


        $builder = Company::query()->select('id', 'name');

        // 考虑东莞市的列子
        if ($level == 3) {
            $builder->where('district_id', $street_id);
        } else {
            $builder->where('area_id', $street_id);
        }

        if ($company_name) {
            $builder->where('name', 'like', "%{$company_name}%");
        }

        switch ($type) {
            // 注册人数
            case 'register_count':
                $builder->withCount('users as register_count')
                    ->withCount('course_learn_records as train_count')
                    ->withCount('user_exams as check_count')
                    ->orderBy('register_count', 'desc');
                break;
            // 培训人数
            case 'train_count':
                $builder->withCount('users as register_count')
                    ->withCount('course_learn_records as train_count')
                    ->withCount('user_exams as check_count')
                    ->orderBy('train_count', 'desc');
                break;
            // 考核人数
            case 'check_count':
                $builder->withCount('users as register_count')
                    ->withCount('course_learn_records as train_count')
                    ->withCount('user_exams as check_count')
                    ->orderBy('check_count', 'desc');
                break;
        }

        $companies = $builder->paginate();
2年前 评论

把 register_count 存到表里面去,才行

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!