Symfony API Platform分页能否设置从page=0开始?
如何将API Platform的页码起始从page=1改为page=0
API Platform官方确实没有提供直接修改页码起始值的配置项,需要通过自定义逻辑实现,下面提供两种可行方案:
方案一:自定义Doctrine查询扩展
通过实现QueryCollectionExtensionInterface,在查询执行前修改请求中的page参数,将0起始的页码转换为Doctrine ORM默认的1起始页码:
- 创建扩展类:
<?php namespace App\Doctrine; use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Metadata\Operation; use Doctrine\ORM\QueryBuilder; use Symfony\Component\HttpFoundation\RequestStack; final class PageZeroPaginationExtension implements QueryCollectionExtensionInterface { public function __construct(private readonly RequestStack $requestStack) { } public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { $request = $this->requestStack->getCurrentRequest(); if (!$request || !$request->query->has('page')) { return; } $inputPage = (int)$request->query->get('page'); // 转换逻辑:page=0 → 1,page=1 → 2,以此类推;小于0的页码默认设为1 $doctrinePage = $inputPage >= 0 ? $inputPage + 1 : 1; $request->query->set('page', $doctrinePage); } }
- 无需额外配置:Symfony会自动识别实现了
QueryCollectionExtensionInterface的类并注册为服务,扩展会自动应用到所有Doctrine ORM驱动的资源查询中。
方案二:自定义分页器
如果需要更精细控制分页元数据的返回格式(比如让lastPage也以0起始),可以自定义实现PaginatorInterface:
- 创建自定义分页器:
<?php namespace App\Pagination; use ApiPlatform\State\Pagination\PaginatorInterface; use Doctrine\ORM\Query; use Doctrine\ORM\Tools\Pagination\Paginator as DoctrinePaginator; class ZeroBasedPaginator implements PaginatorInterface { private DoctrinePaginator $doctrinePaginator; private int $currentPage; private int $itemsPerPage; public function __construct(Query $query, int $page, int $itemsPerPage) { $this->currentPage = $page; $this->itemsPerPage = $itemsPerPage; // 将0起始页码转换为Doctrine分页需要的1起始页码 $doctrinePage = $page >= 0 ? $page + 1 : 1; $query ->setFirstResult(($doctrinePage - 1) * $itemsPerPage) ->setMaxResults($itemsPerPage); $this->doctrinePaginator = new DoctrinePaginator($query); } public function getCurrentPage(): float { return $this->currentPage; // 返回0起始的当前页码 } public function getItemsPerPage(): float { return $this->itemsPerPage; } public function getLastPage(): float { // 将Doctrine的1起始最后页码转换为0起始 $totalItems = $this->doctrinePaginator->count(); return $totalItems > 0 ? ceil($totalItems / $this->itemsPerPage) - 1 : 0; } public function getTotalItems(): float { return $this->doctrinePaginator->count(); } public function getIterator(): \Traversable { return $this->doctrinePaginator->getIterator(); } }
- 在资源中指定使用该分页器:
use ApiPlatform\Metadata\ApiResource; use App\Pagination\ZeroBasedPaginator; #[ApiResource( paginationPaginator: ZeroBasedPaginator::class, paginationEnabled: true )] class YourEntity { // 实体属性及其他配置 }
这个方案会让返回的分页元数据(currentPage、lastPage)都保持0起始的格式,更符合前端的预期。
内容的提问来源于stack exchange,提问作者Rayiez
相关产品推荐
相关产品推荐

