Symfony分页组件排序参数名无法自定义问题排查
问题:多分页对象下排序参数名修改无效
环境信息
| 依赖类型 | 版本号 |
|---|---|
| Bundle版本 | 5.9.0 |
| 组件版本 | 3.6.0 |
| Symfony版本 | 6.4.2 |
| PHP版本 | 8.3.2 |
在单页面中使用多个分页对象,希望修改各自的排序和分页参数名避免冲突。分页参数通过pageParameterName可以正常修改,但使用文档提到的sortFieldParameterName和sortDirectionParameterName修改排序参数名毫无效果,参数仍为默认值。仅希望在当前函数中修改这些参数,不影响应用其他部分。
位置列表控制器代码
/** * Function to display all locations in the system * * @author Daniel Boling */ #[Route('/location/list/', name:'loc_list')] public function loc_list(Request $request): Response { if (isset($request->query->all()['loc_code'])) { $loc = $this->loc_repo->find($request->query->all()['loc_code']); } else { $loc = new Location; } $loc_form = $this->createForm(LocationType::class, $loc); $loc_thead = [ 'loc_code' => 'Loc Code', 'loc_desc' => 'Loc Desc', 'loc_notes' => 'Loc Notes', 'item_total_qty' => 'Item Total Qty.', ]; $result = $this->loc_repo->findAll(); $result = $this->paginator->paginate($result, $request->query->getInt('loc_page', 1), 1, ['sortFieldParameterName' => 'loc_sort', 'sortDirectionParameterName' => 'loc_direction', 'pageParameterName' => 'loc_page']); $normalized_locations = []; foreach ($result->getItems() as $item) { $normalized_locations[] = [ 'loc_code' => $item->getLocCode(), 'loc_desc' => $item->getLocDesc(), 'loc_notes' => $item->getLocNotes(), 'item_total_qty' => $item->getItemQty(), ]; } $result->setItems($normalized_locations); return $this->render('location/loc_list.html.twig', [ 'locations' => $result, 'loc_thead' => $loc_thead, 'form' => $loc_form, ]); }
物品表格片段控制器代码
/** * Fetches selected location's items for template fragment * * @author Daniel Boling */ public function loc_items_list(Request $request, ?string $loc_code, ?int $item_page = 1): Response { $loc = $this->loc_repo->find($loc_code); $item_thead = [ 'item_code' => 'Item Code', 'item_desc' => 'Item Desc', 'item_unit' => 'Item Unit', 'item_notes' => 'Item Notes', 'item_exp_date' => 'Item Exp. Date', 'item_qty' => 'Item Total Qty.', ]; // to autofill form fields, or leave them null. $result = $this->item_repo->findByLoc($loc_code); $result = $this->paginator->paginate($result, $item_page, 10, ['pageParameterName' => 'item_page', 'sortParameterName' => 'item_sort', 'sortDirectionParameterName' => 'item_direction']); $normalized_items = []; foreach ($result->getItems() as $item) { $normalized_items[] = [ 'item_code' => $item->getItemCode(), 'item_desc' => $item->getItemDesc(), 'item_notes' => $item->getItemNotes(), 'item_exp_date' => $item->getItemExpDate(), 'item_qty' => $item->getItemQty(), 'item_unit' => $item->getItemUnit()->getUnitCode(), ]; } $result->setItems($normalized_items); return $this->render('location/item_table.html.twig', [ 'items' => $result, 'item_thead' => $item_thead, ]); }
解决方案
问题出在两个关键地方:控制器参数名错误,以及Twig模板未配合使用自定义排序参数。
1. 修正控制器中的参数名称
在物品表格控制器中,你错误使用了sortParameterName,正确的参数名应该是sortFieldParameterName,和位置列表控制器保持一致。修改后的分页代码:
$result = $this->paginator->paginate( $result, $item_page, 10, [ 'pageParameterName' => 'item_page', 'sortFieldParameterName' => 'item_sort', // 修正此处参数名 'sortDirectionParameterName' => 'item_direction' ] );
2. Twig模板必须指定自定义排序参数
仅在控制器配置参数还不够,渲染分页链接时需要明确告诉KnpPaginator使用你自定义的参数名。
位置列表模板示例
{# 渲染排序表头链接 #} {% for label, field in loc_thead %} <th> <a href="{{ path('loc_list', app.request.query.all|merge({ loc_sort: field, loc_direction: locations.sortDirection == 'asc' ? 'desc' : 'asc' })) }}"> {{ label }} {% if locations.sortField == field %} {{ locations.sortDirection == 'asc' ? '↑' : '↓' }} {% endif %} </a> </th> {% endfor %} {# 渲染分页控件 #} {{ knp_pagination_render(locations, '', { 'pageParameterName': 'loc_page', 'sortFieldParameterName': 'loc_sort', 'sortDirectionParameterName': 'loc_direction' }) }}
物品表格模板示例
{# 渲染排序表头链接 #} {% for label, field in item_thead %} <th> <a href="{{ path(app.request.attributes.get('_route'), app.request.query.all|merge({ item_sort: field, item_direction: items.sortDirection == 'asc' ? 'desc' : 'asc' })) }}"> {{ label }} {% if items.sortField == field %} {{ items.sortDirection == 'asc' ? '↑' : '↓' }} {% endif %} </a> </th> {% endfor %} {# 渲染分页控件 #} {{ knp_pagination_render(items, '', { 'pageParameterName': 'item_page', 'sortFieldParameterName': 'item_sort', 'sortDirectionParameterName': 'item_direction' }) }}
3. 用QueryBuilder支持动态排序
你当前直接使用findByLoc获取结果,这种静态查询无法支持动态排序。需要改用QueryBuilder构建查询,让分页器能正确应用排序规则:
public function loc_items_list(Request $request, ?string $loc_code): Response { // 获取自定义参数 $itemPage = $request->query->getInt('item_page', 1); $sortField = $request->query->get('item_sort'); $sortDirection = $request->query->get('item_direction', 'asc'); $loc = $this->loc_repo->find($loc_code); $item_thead = [ 'item_code' => 'Item Code', 'item_desc' => 'Item Desc', 'item_unit' => 'Item Unit', 'item_notes' => 'Item Notes', 'item_exp_date' => 'Item Exp. Date', 'item_qty' => 'Item Total Qty.', ]; // 用QueryBuilder构建可排序的查询 $queryBuilder = $this->item_repo->createQueryBuilder('i') ->where('i.locCode = :locCode') ->setParameter('locCode', $loc_code); // 应用排序规则 if ($sortField && in_array($sortField, array_keys($item_thead))) { $queryBuilder->orderBy('i.' . $sortField, $sortDirection); } $result = $this->paginator->paginate( $queryBuilder, $itemPage, 10, [ 'pageParameterName' => 'item_page', 'sortFieldParameterName' => 'item_sort', 'sortDirectionParameterName' => 'item_direction' ] ); // 后续标准化逻辑... }
内容的提问来源于stack exchange,提问作者Daniel Boling
相关产品推荐
相关产品推荐

