You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony API Platform分页能否设置从page=0开始?

如何将API Platform的页码起始从page=1改为page=0

API Platform官方确实没有提供直接修改页码起始值的配置项,需要通过自定义逻辑实现,下面提供两种可行方案:

方案一:自定义Doctrine查询扩展

通过实现QueryCollectionExtensionInterface,在查询执行前修改请求中的page参数,将0起始的页码转换为Doctrine ORM默认的1起始页码:

  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);
    }
}
  1. 无需额外配置:Symfony会自动识别实现了QueryCollectionExtensionInterface的类并注册为服务,扩展会自动应用到所有Doctrine ORM驱动的资源查询中。

方案二:自定义分页器

如果需要更精细控制分页元数据的返回格式(比如让lastPage也以0起始),可以自定义实现PaginatorInterface:

  1. 创建自定义分页器:
<?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();
    }
}
  1. 在资源中指定使用该分页器:
use ApiPlatform\Metadata\ApiResource;
use App\Pagination\ZeroBasedPaginator;

#[ApiResource(
    paginationPaginator: ZeroBasedPaginator::class,
    paginationEnabled: true
)]
class YourEntity
{
    // 实体属性及其他配置
}

这个方案会让返回的分页元数据(currentPage、lastPage)都保持0起始的格式,更符合前端的预期。

内容的提问来源于stack exchange,提问作者Rayiez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 05:35:05