pacolmg / symfony-filter-bundle
用于在Symfony 4实体仓库中过滤对象的轻量级库
Requires
- php: ^7.1.3
- symfony/config: ^3.4 || ^4.0 || ^4.3 || ^4.4
- symfony/dependency-injection: ^3.4 || ^4.2 || ^4.3 || ^4.4
- symfony/http-kernel: ^3.4 || ^4.0 || ^4.3 || ^4.4
Requires (Dev)
- symfony/browser-kit: ^3.4 || ^4.0 || ^4.3 || ^4.4
- symfony/framework-bundle: ^3.4 || ^4.2 || ^4.3 || ^4.4
- symfony/phpunit-bridge: ^3.4 || ^4.0 || ^4.3 || ^4.4
This package is auto-updated.
Last update: 2024-09-29 05:45:46 UTC
README
此包为您的Symfony 4应用程序提供了一些方便的过滤和列表创建功能。
许可MIT
安装
通过控制台使用composer添加包
$ composer require pacolmg/symfony-filter-bundle
将Bundle添加到config/bundles.php
可能您可以跳过此步骤,因为Symfony Flex会自动完成。但以防万一,请转到文件 config\bundles.php 并检查以下行是否在代码中
... Pacolmg\SymfonyFilterBundle\PacolmgSymfonyFilterBundle::class => ['all' => true], ...
扩展需要过滤的实体仓库
例如,在一个名为Article的实体中,其仓库应位于src\Repository\ArticleRepository.php
<?php namespace App\Repository; use Pacolmg\SymfonyFilterBundle\Repository\BaseRepository; ... class ArticleRepository extends BaseRepository { ...
现在,安装已完成,Article仓库将拥有新的方法,以便根据不同的字段和不同的方式(如,大于等)查找对象。
可以扩展多个仓库。
使用方法
开始过滤仓库
方法getAll
要从扩展的仓库中过滤对象,应调用仓库的getAll方法
$this->entityManager->getRepository('App:Article')->getAll($filters, $orderBy, $limit, $offset);
参数
- offset:第一个结果(用于分页)。
- limit:最大结果数(用于分页)。
- orderby:它是一个数组,格式如下
[字段 => '方向'].- 示例:
['title' => 'ASC']。 - 因此,结果可以按多个字段排序。
参数$ filter
它是唯一必需的参数,由不同格式的过滤器数组组成
[
'type' => Constant that defines the behaviour,
'field' => Field of the Entity (Or fields, separated by pipe ("|")) where search the value,
'value' => Value to compare
]
**字段可以允许有多个值,这些值由竖线|分隔,以在多个字段中搜索相同的值。
过滤器类型
BaseRepository::FILTER_EXACT:比较字段是否等于值。BaseRepository::FILTER_LIKE:比较字段是否类似于值。BaseRepository::FILTER_IN:在值数组中搜索字段。BaseRepository::FILTER_GREATER:比较字段是否大于值。BaseRepository::FILTER_GREATER_EQUAL:比较字段是否大于等于值。BaseRepository::FILTER_LESS:比较字段是否小于值。BaseRepository::FILTER_LESS_EQUAL:比较字段是否小于等于值。BaseRepository::FILTER_DIFFERENT:比较字段是否不等于值。
方法getAllCount
如果需要结果数,则getAllCount方法将返回该数,只需将过滤器传递给该方法即可。
$this->entityManager->getRepository('App:Article')->getAllCount($filters);
示例
因此,在解释了可以使用哪些过滤器之后,如果我们需要包含标题中包含单词tree的文章,我们应该编写以下代码
$data = $this->entityManager->getRepository('App:Article')->getAll([ [ 'type': BaseRepository::FILTER_LIKE, 'field': 'title', 'value': 'tree' ] ]);
简单吗?那么,现在,我们将查找标题中包含tree且在标题或正文中包含cat的文章
$data = $this->entityManager->getRepository('App:Article')->getAll([ [ 'type': BaseRepository::FILTER_LIKE, 'field': 'title', 'value': 'tree' ], [ 'type': BaseRepository::FILTER_LIKE, 'field': 'title|body', 'value': 'cat' ] ]);
结果太多?如果需要,我们可以按publishDate排序结果并过滤它们,因为我们只对当前年份感兴趣
$data = $this->entityManager->getRepository('App:Article')->getAll([ [ 'type': BaseRepository::FILTER_LIKE, 'field': 'title', 'value': 'tree' ], [ 'type': BaseRepository::FILTER_LIKE, 'field': 'title|body', 'value': 'cat' ], [ 'type': BaseRepository::FILTER_GREATER_EQUAL, 'field': 'publishDate', 'value': date('Y-01-01 00:00') ], [ 'type': BaseRepository::FILTER_LESS_EQUAL, 'field': 'publishDate', 'value': date('Y-31-12 23:59') ] ], ['publishDate' => 'DESC']);
结果仍然很多吗?我们应该进行分页,我们想看到第二页,每页显示10个结果
$data = $this->entityManager->getRepository('App:Article')->getAll([ [ 'type': BaseRepository::FILTER_LIKE, 'field': 'title', 'value': 'tree' ], [ 'type': BaseRepository::FILTER_LIKE, 'field': 'title|body', 'value': 'cat' ], [ 'type': BaseRepository::FILTER_GREATER_EQUAL, 'field': 'publishDate', 'value': date('Y-01-01 00:00') ], [ 'type': BaseRepository::FILTER_LESS_EQUAL, 'field': 'publishDate', 'value': date('Y-31-12 23:59') ] ], ['publishDate' => 'DESC'], 2, 10);
如果您需要在网站上显示结果,您可能需要显示元素的总数,以便进行显示或适当的分页,这很简单
$totalResults = $this->entityManager->getRepository('App:Article')->getAllCount([ [ 'type': BaseRepository::FILTER_LIKE, 'field': 'title', 'value': 'tree' ], [ 'type': BaseRepository::FILTER_LIKE, 'field': 'title|body', 'value': 'cat' ], [ 'type': BaseRepository::FILTER_GREATER_EQUAL, 'field': 'publishDate', 'value': date('Y-01-01 00:00') ], [ 'type': BaseRepository::FILTER_LESS_EQUAL, 'field': 'publishDate', 'value': date('Y-31-12 23:59') ] ]);
方法 getDistinctField
可能需要字段的不同值来过滤选择,请以字段名称作为参数调用此函数。
$this->entityManager->getRepository('App:Article')->getAllCount($field);
示例
我们需要将实体的所有不同作者放入选择中
$authors = $this->entityManager->getRepository('App:Article')->getAllCount('author');
使用服务进行过滤
该包提供了一个服务:Pacolmg\SymfonyFilterBundle\Service\FilterService;
在此服务中,将仓库的 getAll 和 getAllCount 方法合并,因此服务中的 getFiltered 方法将返回仓库的对象集合和元素总数,以帮助控制器和视图进行分页。
排序参数具有不同的格式,以便传递字段和方向,避免编写数组。
$this->filterService->getFiltered( $repository, $filters, $page, $limit, $sortBy, $sortDir );
示例
以下示例,从服务或控制器进行编码的最后一步
$this->filterService->getFiltered( $this->entityManager->getRepository('App:Article'), [ [ 'type': BaseRepository::FILTER_LIKE, 'field': 'title', 'value': 'tree' ], [ 'type': BaseRepository::FILTER_LIKE, 'field': 'title|body', 'value': 'cat' ], [ 'type': BaseRepository::FILTER_GREATER_EQUAL, 'field': 'publishDate', 'value': date('Y-01-01 00:00') ], [ 'type': BaseRepository::FILTER_LESS_EQUAL, 'field': 'publishDate', 'value': date('Y-31-12 23:59') ] ], 2, 10, 'publishDate', 'DESC' );
此示例将返回一个包含两个键的数组
[ 'data' => colection of objects, 'total' => Total number of elements filtered by $filters ]
从控制器进行过滤
为了与网站完全集成,该包还提供了一个其他服务 Pacolmg\SymfonyFilterBundle\Service\ExternalParametersService,其中包含一些从 Request 获取参数的方法。
获取页面和限制
getPageAndLimit 方法以数组形式返回页面和每页元素数。它从参数 page 和 limit 获取信息。
示例
在控制器中,我们可以这样编写,变量 $page 和 $limit 将具有页面和每页元素数,最小页面为 1,最大限制为 500。
list($page, $limit) = $this->externalParametersService->getPageAndLimit($request);
获取过滤器
getFilters 方法需要 $request 和 $filters,并将返回它们的值。为了使其工作,我们需要为每个过滤器添加一对字段
[
'type' => Constant that defines the behaviour,
'field' => Field of the Entity (Or fields separated by pipe ("|")) where find the value,
'request_type' => Type of the value
'request_name' => Name of the parameter
]
请求类型
request_type 的类型可以是
- int
- string (默认)
- bool
- array
- date
示例
我们有一个带搜索输入的网站,该输入将参数 t 的值发送到控制器,我们想使用这个参数来查找类似于参数 t 的标题
http://mywebsite.com?t=tree
在控制器中,我们应该这样编写
$filters = $this->entityManager->getRepository('App:Article')->getAll([ [ 'type': BaseRepository::FILTER_LIKE, 'field': 'title', 'request_type': 'string', 'request_name': 't' ] ]); list($data, $totalData) = $this->filterService->getFiltered($filters);
在下一个示例中,我们有一些分页参数
http://mywebsite.com?t=tree&page=2&limit=10
因此,控制器中的代码将是这样的
list($page, $limit) = $this->externalParametersService->getPageAndLimit($request); $filters = $this->entityManager->getRepository('App:Article')->getAll([ [ 'type': BaseRepository::FILTER_LIKE, 'field': 'title', 'request_type': 'string', 'request_name': 't' ] ]); list($data, $totalData) = $this->filterService->getFiltered($filters, $page, $limit);
从视图进行过滤
该包还希望帮助您在视图中使用表单,因此您可以包含一些预定义的字段,或者扩展您完整的表单 "@PacolmgSymfonyFilter/filters/layout.html.twig"
###输入预定义的字段
- 文本输入: @PacolmgSymfonyFilter/filters/input.html.twig
- 数字输入: @PacolmgSymfonyFilter/filters/number.html.twig
- 日期时间本地输入 (仅在chrome中工作): @PacolmgSymfonyFilter/filters/date.html.twig
- 选择: @PacolmgSymfonyFilter/filters/select.html.twig
参数
每个输入都有一些常见的参数
- name (string,必需):输入的属性名称。
- id (string,非必需):输入的id。如果没有定义,则id为:symfony_filter_form_+name。
- class (string,非必需):输入的类。如果没有定义,则类为 form-control。
- placeholder (string,非必需):输入的占位符。
- print_label (boolean,非必需):是否打印字段的标签。
- label (string,非必需):字段的标签。如果没有定义且 print_label 为 true,则标签为占位符。标签可以是 HTML。
- defaultData (string
|array|int,非必需):字段的默认值。 - attrs (array):输入的可选属性。
选择字段类型将有两个其他参数,其中一个是必需的
- options (array,必需):选项数组
- 数组选项的格式为:[值 => 文本, 值 => 文本, ...]
- multiple (布尔值,非必须):是否为多选。默认为False。
示例
我们仍然想找到标题包含特定单词的文章,这个单词将从视图中的输入收集。我们还希望按日期和状态过滤它们,因此表单的一个例子可能是
{% raw %}
{% extends "@PacolmgSymfonyFilter/layout.html.twig" %}
{% block pacolmg_symfony_filter_bundle_form_filters %}
<div class="col-sm-2">
{{ include('@PacolmgSymfonyFilter/filters/text.html.twig', {placeholder: 'Title', name: 't'}, with_context = false) }}
</div>
<div class="col-sm-2">
{{ include('@PacolmgSymfonyFilter/filters/date.html.twig', {placeholder: 'From', name: 'from'}, with_context = false) }}
</div>
<div class="col-sm-2">
{{ include('@PacolmgSymfonyFilter/filters/date.html.twig', {placeholder: 'To', name: 'to'}, with_context = false) }}
</div>
<div class="col-sm-2">
{{ include('@PacolmgSymfonyFilter/filters/select.html.twig', {placeholder: 'status', name: 's', options: {'1':'Created', '2':'Published', '3':'Deleted'} }, with_context = false) }}
</div>
{% endblock %}
{% endraw %}
这个表单将只传递参数,以便在编码时捕捉它们
$filters = $this->entityManager->getRepository('App:Article')->getAll([ [ 'type': BaseRepository::FILTER_LIKE, 'field': 'title', 'request_type': 'string', 'request_name': 't' ], [ 'type': BaseRepository::FILTER_GREATER_EQUAL, 'field': 'publishedAt', 'request_type': 'date', 'request_name': 'from' ], [ 'type': BaseRepository::FILTER_LESS_EQUAL, 'field': 'publishedAt', 'request_type': 'date', 'request_name': 'to' ], [ 'type': BaseRepository::FILTER_EXACT, 'field': 'status', 'request_type': 'int', 'request_name': 's' ] ]); list($data, $totalData) = $this->filterService->getFiltered($filters);
想象一下,你改变了主意,更愿意获取可以发布或创建的文章,因此我们需要将状态选择转换为多选
... <div class="col-sm-2"> {% raw %} {{ include('@PacolmgSymfonyFilter/filters/select.html.twig', {placeholder: 'status', name: 's', options: {'1':'Created', '2':'Published', '3':'Deleted'} }, with_context = false) }} {% endraw %} </div> ...
然后在控制器中,更改过滤器的类型
... [ 'type': BaseRepository::FILTER_IN, 'field': 'status', 'request_type': 'int', 'request_name': 's' ] ...
分页
因此,在控制器、服务和仓库中,可以通过分页获取结果。该捆绑包还提供了一个twig,使分页开发变得简单。只需包含 '@PacolmgSymfonyFilter/components/pagination.html.twig' 视图,即可查看页面。
参数
必填参数包括
- nbPages (整数,必填):总页数。
- currentPage (整数,必填):当前页。
- url (字符串,必填):用于分页重定向的symfony路由。
- params (数组,必填):路由需要工作的参数(id,q,...)。
twig还有一些可选参数
- nearbyPagesLimit (整数,非必须):当前页周围的页面数。
- 默认值为4。
- align (字符串,非必须):值必须是: "end", "center" 或 "start"(基于bootstrap flex)。
- 默认值为 "end"。
- classPageItem (字符串,非必须):"li"标签的类。
- 默认值为 "page-item"。
- classPageLink (字符串,非必须):链接的类。
- 默认值为 "page-link"。
- classDisabled (字符串,非必须):禁用页面的类。
- 默认值为 "disabled"。
- classActive (字符串,非必须):当前页的类。
- 默认值为 "active"。
示例
我们有自己的文章索引页面,其中包含前面示例中定义的过滤器,现在我们想显示页数
为了避免在twig中过多逻辑,我们在控制器中构建参数
list($page, $limit) = $this->externalParametersService->getPageAndLimit($request); $filters = $this->entityManager->getRepository('App:Article')->getAll([ ... ]); list($data, $totalData) = $this->filterService->getFiltered($filters); $paginationData = [ 'nbPages' => ceil($data['total'] / $limit), 'currentPage' => $page, 'url' => $request->get('_route'), 'params' => $request->query->all() ];
在视图中
{% raw %}
{{ include('@PacolmgSymfonyFilter/components/pagination.html.twig', paginationData, with_context = false) }}
{% endraw %}
希望这个捆绑包的过滤和分页你的实体不再痛苦。