bugloos / query-filter-bundle
查询过滤器包允许您从QueryBuilder和数据库中过滤数据。您可以同时过滤多个列,也可以在查询构建器中对关联字段进行两级深度过滤,而不需要任何连接。
Requires
- php: >=8.1
- doctrine/annotations: ^2.0
- doctrine/doctrine-bundle: ^2.2
- doctrine/orm: ^2.8
- psr/cache: ^1.0 | ^2.0 | ^3.0
- symfony/framework-bundle: ^4.4 | ^5.4 | ^6.0
- symfony/http-kernel: ^4.4 | ^5.4 | ^6.0
- symfony/orm-pack: ^2.2
Requires (Dev)
- ext-json: *
- friendsofphp/php-cs-fixer: ^3.8
- matthiasnoback/symfony-dependency-injection-test: ^4.1
- phpunit/phpunit: ^9.5
- roave/security-advisories: dev-latest
- symfony/browser-kit: ^5.4
- symfony/http-client: ^5.4
- zenstruck/foundry: ^1.16
README
它是做什么的? :)
查询过滤器包允许您从QueryBuilder和数据库中过滤数据。您可以同时过滤多个列,也可以在查询构建器中对关联字段进行两级深度过滤,而不需要任何连接。安装
composer require bugloos/query-filter-bundle
兼容性
- PHP v7.4或更高版本
- Symfony v4.4或更高版本
使用
假设我们的数据库有以下表以及以下关系现在我们想过滤书籍实体
我们想通过title列过滤书籍实体,因此我们可以通过查询字符串或以下内联代码中的数组发送过滤数据
/* * Filter books by title column */ //Get api/book/index?filter[title]=text_for_search OR $filters = [ 'title' => 'text_for_search', ]; /* * Filter books by title column */ //Get api/book/index?filter[title]=text_for_search OR $filters = [ 'title' => 'text_for_search', ];
您只需要在控制器中添加QueryFilter类
use Bugloos\QueryFilterBundle\Service\QueryFilter;
以下代码在书籍控制器中。
如您所见,首先您应该调用for()方法并将QueryBuilder作为参数传递给此方法
然后调用parameters()方法并传递过滤请求项
最后,您应该调用filter()方法来运行它
filter方法的返回值是QueryBuilder,因此您可以在过滤后向QueryBuilder添加任何其他内容。public function index( Request $request, BookRepository $bookRepository, QueryFilter $queryFilter ): Response { $queryBuilder = $bookRepository->createQueryBuilder('b'); $queryBuilder = $queryFilter->for($queryBuilder) ->parameters($request->get('filters')) ->filter() ; return $queryBuilder->getQuery()->getResult(); }
如果您想过滤ManyToOne关联字段或一级深度关系,您应该添加映射器。
要添加映射器,您可以通过调用addMapper()方法添加单个映射器或通过调用mappers()方法通过数组添加多个映射器
addMapper()方法的第一参数是参数名称,第二参数是关系名称及其字段名称,字段名称由" . "符号分隔
$mappers = [ 'country' => 'country.name', ];
例如,我们想通过其国家名称过滤书籍实体。书籍与国家实体具有ManyToOne关系
/* * Filter books by country column */ //Get api/book/index?filter[country]=text_for_search OR $filters = [ 'country' => 'text_for_search', ]; /* * Filter books by country column */ //Get api/book/index?filter[country]=text_for_search OR $filters = [ 'country' => 'text_for_search', ];
以下代码在书籍控制器中。
public function index( Request $request, BookRepository $bookRepository, QueryFilter $queryFilter ): Response { $queryBuilder = $bookRepository->createQueryBuilder('b'); $queryBuilder = $queryFilter->for($queryBuilder) ->parameters($request->get('filters')) ->addMapper('country', 'country.name') ->filter() ; return $queryBuilder->getQuery()->getResult(); }
注意:不需要在QueryBuilder中添加您的关联连接,因为如果不添加连接,我会自动添加它。 ;)
$queryBuilder = $bookRepository->createQueryBuilder('b'); OR $queryBuilder = $bookRepository->createQueryBuilder('b') ->addSelect('country') ->leftJoin('b.country', 'country') ;
如果您想过滤ManyToMany关联字段或两级深度关系,您应该再次添加映射器
$mapper = [ 'age' => 'bookUsers.user.age', ];
例如,我们想通过其作者的年龄过滤书籍实体
/* * Filter books by Writers age column */ //Get api/book/index?filter[age]=31 OR $filters = [ 'age' => 31, ]; /* * Filter books by Writers age column */ //Get api/book/index?filter[age]=31 OR $filters = [ 'age' => 31, ];
以下代码在书籍控制器中。
public function index( Request $request, BookRepository $bookRepository, QueryFilter $queryFilter ): Response { $queryBuilder = $bookRepository->createQueryBuilder('b'); $queryBuilder = $queryFilter->for($queryBuilder) ->parameters($request->get('filters')) ->addMapper('age', 'bookUsers.user.age') ->sort() ; return $queryBuilder->getQuery()->getResult(); }
注意:您还可以使用多个列过滤数据,只需发送多个过滤数据作为查询字符串即可
/* * Filter books by title and age */ //Get api/book/index?filter[title]=text&filter[age]=31 OR $filters = [ 'title' => 'text', 'age' => 31, ];
建议
您可以通过配置文件更改两个参数,只需在config/packages/目录中创建一个yaml文件,然后您可以更改查询的默认缓存时间和默认关系分隔符如下
query_filter: default_cache_time: 3600 separator: '.'
注意:您可以分别为每个查询设置缓存时间,如果您没有设置任何缓存时间,则使用配置文件中的默认缓存时间
$queryBuilder = $queryFilter->for($queryBuilder) ->parameters($request->get('filters')) ->cacheTime(120) ->sort() ;
贡献力量

如果你发现了一个问题,或者有更好的方法来做某事,请随时提交一个issue或者pull request。
