JQGrid(loadonce=false)分页与列筛选失效问题求助(Laravel 5.8后端)
解决Laravel 5.8 + jqGrid 4.6分页与筛选问题
我之前刚好处理过Laravel配合jqGrid的类似场景,你遇到的问题核心是当loadonce: false时,jqGrid会把分页、排序、筛选的参数都通过URL传给后端,需要你在Laravel里对应处理这些参数,然后返回符合jqGrid格式的响应。先给你拆解下你看到的请求参数含义,再一步步写后端实现。
一、先搞懂jqGrid传的请求参数含义
你看到的URL参数里,每个字段的作用是:
_search: 布尔值,标识是否有筛选条件(true=有筛选,false=无)nd: 时间戳,用来防止缓存,后端可以直接忽略rows: 每页显示的记录数(分页大小)page: 当前请求的页码sidx: 排序的列名(对应你数据库的字段,比如你这里的NUM_CERFA)sord: 排序方向(asc=升序,desc=降序)
如果是列筛选触发的请求,还会多一个filters参数,是JSON格式的筛选条件,后面会讲怎么解析。
二、Laravel后端实现步骤
假设你的模型是Cerfa,对应的控制器是CerfaController,方法对应你的路由listes/cerfa/json/null,下面是具体代码:
1. 接收请求参数
在控制器方法里,先获取所有请求参数:
use Illuminate\Http\Request; use App\Models\Cerfa; // 假设你的模型路径是这个 public function jsonList(Request $request) { // 获取分页与排序参数,设置默认值防止空参数报错 $page = $request->get('page', 1); $rowsPerPage = $request->get('rows', 10); $sortField = $request->get('sidx', 'NUM_CERFA'); $sortDirection = $request->get('sord', 'asc'); $isSearch = $request->get('_search', false); $filters = $request->get('filters', ''); }
2. 构建查询(处理筛选、排序)
先初始化基础查询,再根据筛选条件和排序参数调整:
// 初始化基础查询 $query = Cerfa::query(); // 处理筛选条件 if ($isSearch && !empty($filters)) { // 解析jqGrid的filters JSON字符串 $filterRules = json_decode($filters, true); if (isset($filterRules['rules'])) { $groupOp = $filterRules['groupOp'] ?? 'AND'; // 默认AND逻辑 if ($groupOp === 'AND') { foreach ($filterRules['rules'] as $rule) { $this->addFilterCondition($query, $rule); } } else { // OR逻辑需要用闭包包裹 $query->orWhere(function ($q) use ($filterRules) { foreach ($filterRules['rules'] as $rule) { $this->addFilterCondition($q, $rule); } }); } } } // 处理排序 $query->orderBy($sortField, $sortDirection); // 封装筛选条件的私有方法,避免重复代码 private function addFilterCondition($query, $rule) { $field = $rule['field']; $op = $rule['op']; $value = $rule['data']; switch ($op) { case 'eq': $query->where($field, '=', $value); break; case 'cn': $query->where($field, 'like', "%{$value}%"); break; case 'gt': $query->where($field, '>', $value); break; case 'lt': $query->where($field, '<', $value); break; case 'ne': $query->where($field, '!=', $value); break; case 'ge': $query->where($field, '>=', $value); break; case 'le': $query->where($field, '<=', $value); break; // 可以根据你的需求添加更多操作符 } }
3. 处理分页并计算总数据
用Laravel的查询构造器手动处理分页,同时计算总记录数和总页数:
// 获取总记录数 $totalRecords = $query->count(); // 计算总页数 $totalPages = ceil($totalRecords / $rowsPerPage); // 获取当前页数据 $cerfas = $query->skip(($page - 1) * $rowsPerPage)->take($rowsPerPage)->get();
4. 组装jqGrid需要的响应格式
jqGrid要求返回的JSON必须包含total(总页数)、page(当前页)、records(总记录数)、rows(当前页数据数组):
// 把模型数据转换成jqGrid需要的格式 $rowsData = $cerfas->map(function ($cerfa) { return [ 'id' => $cerfa->id, // jqGrid推荐每行带唯一id,方便后续操作 'cell' => [ $cerfa->NUM_CERFA, $cerfa->你的字段1, $cerfa->你的字段2, // 顺序要和你jqGrid列配置的顺序完全对应 ] ]; })->toArray(); // 返回JSON响应 return response()->json([ 'total' => $totalPages, 'page' => $page, 'records' => $totalRecords, 'rows' => $rowsData ]);
三、注意事项
- 确保jqGrid列配置的
name属性和数据库字段名完全对应,否则排序和筛选会失效。 - 测试时可以直接在浏览器访问带参数的URL,查看返回的JSON格式是否符合要求,再结合Network Tab排查问题。
- 如果需要处理更复杂的筛选(比如日期范围),可以在
addFilterCondition方法里扩展对应的操作符逻辑。
内容的提问来源于stack exchange,提问作者Hippolyte Massiot




