ekrouzek / pagination-filters-bundle
分页、排序和分页请求过滤器组件。
Requires
- php: >=8.0.1
- doctrine/orm: ^2.11
- friendsofsymfony/rest-bundle: ^3.3
- nette/utils: ^3.2
README
Symfony 组件,允许您为选定的 API 端点设置分页、过滤和排序。
安装
1. 下载组件
要下载此组件的最新稳定版本,打开命令行,切换到您的项目目录,并执行以下命令
composer require ekrouzek/pagination-filters-bundle
2. 启用组件
如果使用 Flex,组件将自动启用。但是,如果不使用 Flex,则需要手动在项目中的 config/bundles.php 文件中添加以下行来启用组件。
<?php // config/bundles.php return [ // ... Ekrouzek\PaginationFiltersBundle\PaginationFiltersBundle::class => ['all' => true], // ... ];
实现
示例 GET 端点获取所有课程的用法
1. 标头和 ParamFetcher
首先,需要指定方法期望的查询参数
#[QueryParam(name: "page", requirements: "\d+", default: 1)] #[QueryParam(name: "itemsPerPage", requirements: "\d+", default: 10)] #[QueryParam(name: "filter", default: "")] #[QueryParam(name: "sort", default: "")]
然后您还需要将 ParamFetcher 添加到函数参数中
public function getCourses(ParamFetcher $paramFetcher, ...): View
2. 过滤器定义
接下来,只需将可以过滤和排序的数据定义以及相应的 DQL 查询(下文详细介绍)添加到给定方法中即可:提供了 addNumberField()
、addTextField()
、addDatetimeField()
、addBooleanField()
方法。这些函数的第一个参数是向外界展示的键 - 即可以从中外部过滤的键。第二个参数指定它映射到指定 DQL 查询的哪个属性上。
例如
$paginationHandler = new PaginationHandler($paramFetcher); $paginationHandler->createQueryFilter() ->addNumberField("id", "c.id") ->addTextField("semester", "c.semester") ->addTextField("subject", "c.subject") ->addDatetimeField("created", "c.created");
3. 获取 QueryBuilder 和结果
而不是已经获得的结果,需要传递 DQL QueryBuilder 进行评估。因此,需要在仓库中创建自己的方法来获取查询。想法与在仓库中创建自己的方法相同,但最后不调用 ->getQuery()->getResult()
,而是直接传递 QueryBuilder。
例如
public function getAllCoursesQuery(): QueryBuilder { return $this->getEntityManager() ->createQueryBuilder() ->select('c') ->from(Course::class, 'c'); }
最后,只需在相应的 Service 中创建一个方法,将仓库中此方法的输出传递到控制器。要获取查询的最终结果,只需在控制器中调用 ->getPaginatedData($query)
$query = $this->courseService->getAllCoursesQuery(); try { $courses = $paginationHandler->getPaginatedData($query); } catch (PaginationAndFilterException $exception) { return $this->sendBadRequest($exception->getMessage()); }
4. 发送结果
因此,只需序列化并发送结果即可。要使用 _pagination 标头发送结果,只需调用定义的 sendPaginatedResponse()
方法,该方法将序列化数据包装在一个包含分页信息的标头中。
// Create response. $result = $this->courseService->formatMany($courses); return $paginationHandler->sendPaginatedResponse($result);
用法
要使用分页、过滤和分页,只需将相应的 GET 参数添加到 HTTP 请求中。
分页
- 可以使用
page
参数指定希望从服务器返回多少页。 - 可以使用
itemsPerPage
参数指定每页希望有多少项。
过滤
- 通过
filter
参数进行过滤。 - 过滤器必须由单个表达式组成。一个表达式的样子如下:
<method>:<field>:<value>
。 - 表达式中的方法可以是以下之一:
eq, neq, like, not-like, lt, lte, gt, gte
。 - 可以使用逻辑连接词
&
(AND)和|
(OR)将表达式组合成更复杂的结构。 - 您还可以在表达式中使用括号:
(
和)
。 - 因此,过滤器可以如下所示
?filter=eq:id:1
过滤器示例:?filter=(eq:id:1 & like:name:"test") | gt:created:"2020-01-01 00:00:00"
移动操作
- 排序通过
sort
参数进行。 - 目前只能按一个属性进行排序。
- 排序表达式必须是这样:
<字段>:[asc,desc]
。 - 因此,排序可能看起来像这样
?sort=id:asc
?sort=created:desc