zfcampus / zf-doctrine-querybuilder
Apigility Doctrine QueryBuilder 模块
Requires
- php: ^5.6 || ^7.0
- doctrine/doctrine-module: ^1.2 || ^2.1.8
- zendframework/zend-hydrator: ^1.1 || ^2.2.1 || ^3.0
- zendframework/zend-modulemanager: ^2.7.2
- zendframework/zend-mvc: ^2.7.13 || ^3.0.2
- zendframework/zend-servicemanager: ^2.7.6 || ^3.1.1
- zfcampus/zf-api-problem: ^1.2.2
- zfcampus/zf-apigility-doctrine: ^2.1
- zfcampus/zf-hal: ^1.4.2
Requires (Dev)
- doctrine/doctrine-mongo-odm-module: ^0.11 || ^1.0
- doctrine/doctrine-orm-module: ^1.1 || ^2.1.3
- phpunit/phpunit: ^5.7.27 || ^6.5.14 || ^7.5.3
- symfony/yaml: ^2.3 || ^3.0 || ^4.0
- zendframework/zend-coding-standard: ~1.0.0
- zendframework/zend-i18n: ^2.7.3
- zendframework/zend-log: ^2.9.1
- zendframework/zend-serializer: ^2.8
- zendframework/zend-test: ^2.6.1 || ^3.0.1
- zfcampus/zf-apigility-provider: ^1.2
Suggests
- doctrine/doctrine-mongo-odm-module: ^1.0, if you wish to use the Doctrine ODM
- doctrine/doctrine-orm-module: ^1.1 || ^2.1.3, if you wish to use the Doctrine ORM
- ext/mongo: Mongo extension, if using ODM
README
仓库废弃于2019-12-31
此库提供了从数组参数中获取查询构建器指令。此库旨在将 HTTP 请求中的过滤器应用于 API,以提供流畅的过滤和排序语法定义。
哲学
鉴于开发者识别了 A 和 B:A == B 在过滤和排序实体数据的能力和愿望方面。
共享的 Doctrine 实体包含
id integer,
name string,
startAt datetime,
endAt datetime,
开发者 A 或 B 编写 API。资源是一个单一的 Doctrine 实体,数据通过 Doctrine QueryBuilder $objectManager->createQueryBuilder()
进行查询。此模块为其他开发者提供了与 Doctrine 查询构建器相同的过滤和排序能力,但通过请求参数访问,就像 API 作者一样。例如,startAt between('2015-01-09', '2015-01-11');
和 name like ('%arlie')
并非手工艺品 API 的常见过滤器,也许没有此模块,API 作者可能不会实施它。有了此模块的帮助,API 开发者可以轻松实现复杂的可查询性,从而保持 A == B。
安装
此模块的安装使用 composer。有关 composer 文档,请参阅 getcomposer.org。
$ composer require zfcampus/zf-doctrine-querybuilder
安装完成后,将 ZF\Doctrine\QueryBuilder
添加到 config/application.config.php
中的模块列表。
zf-component-installer
如果您使用 zf-component-installer,该插件将为您安装 zf-doctrine-querybuilder 作为模块。
配置模块
将 config/zf-doctrine-querybuilder.global.php.dist
复制到 config/autoload/zf-doctrine-querybuilder.global.php
,并编辑.orm 和 .odm 的别名列表,使其默认启用。
与 Apigility Doctrine 一起使用
要启用所有过滤器,您可以覆盖 zf-apigility-doctrine
中的默认查询提供者。将以下内容添加到您的 zf-doctrine-querybuilder.global.php
配置文件中,如果它们在 $_GET['filter']
或 $_GET['order-by']
请求中,则将应用过滤器和排序。这些 $_GET
键可以通过 zf-doctrine-querybuilder-options
进行自定义。
'zf-apigility-doctrine-query-provider' => [ 'aliases' => [ 'default_orm' => \ZF\Doctrine\QueryBuilder\Query\Provider\DefaultOrm::class, 'default_odm' => \ZF\Doctrine\QueryBuilder\Query\Provider\DefaultOdm::class, ], 'factories' => [ \ZF\Doctrine\QueryBuilder\Query\Provider\DefaultOrm::class => \ZF\Doctrine\QueryBuilder\Query\Provider\DefaultOrmFactory::class, \ZF\Doctrine\QueryBuilder\Query\Provider\DefaultOdm::class => \ZF\Doctrine\QueryBuilder\Query\Provider\DefaultOdmFactory::class, ], ],
使用
配置示例
'zf-doctrine-querybuilder-orderby-orm' => [ 'aliases' => [ 'field' => \ZF\Doctrine\QueryBuilder\OrderBy\ORM\Field::class, ], 'factories' => [ \ZF\Doctrine\QueryBuilder\OrderBy\ORM\Field::class => \Zend\ServiceManager\Factory\InvokableFactory::class, ], ], 'zf-doctrine-querybuilder-filter-orm' => [ 'aliases' => [ 'eq' => \ZF\Doctrine\QueryBuilder\Filter\ORM\Equals::class, ], 'factories' => [ \ZF\Doctrine\QueryBuilder\Filter\ORM\Equals::class => \Zend\ServiceManager\Factory\InvokableFactory::class, ], ],
请求示例
$_GET = [ 'filter' => [ [ 'type' => 'eq', 'field' => 'name', 'value' => 'Tom', ], ], 'order-by' => [ [ 'type' => 'field', 'field' => 'startAt', 'direction' => 'desc', ], ], ];
资源示例
$serviceLocator = $this->getApplication()->getServiceLocator(); $objectManager = $serviceLocator->get('doctrine.entitymanager.orm_default'); $filterManager = $serviceLocator->get('ZfDoctrineQueryBuilderFilterManagerOrm'); $orderByManager = $serviceLocator->get('ZfDoctrineQueryBuilderOrderByManagerOrm'); $queryBuilder = $objectManager->createQueryBuilder(); $queryBuilder->select('row') ->from($entity, 'row') ; $metadata = $objectManager->getMetadataFactory()->getMetadataFor(ENTITY_NAME); // $e->getEntity() using doctrine resource event $filterManager->filter($queryBuilder, $metadata, $_GET['filter']); $orderByManager->orderBy($queryBuilder, $metadata, $_GET['order-by']); $result = $queryBuilder->getQuery()->getResult();
过滤器
过滤器不是简单的键/值对。过滤器是一个没有键的过滤器定义数组。每个过滤器定义都是一个数组,且数组值因过滤器类型而异。
每个过滤器定义至少需要有一个'type'。这个类型引用配置键,例如'eq'、'neq'、'between'。
每个过滤器定义至少需要有一个'field'。这是目标实体上的字段名称。
每个过滤器定义可以指定'where',值为'and'或'or'。
通过AndX和OrX过滤器类型,支持嵌入式逻辑,如and(x or y)。
构建HTTP GET查询
JavaScript示例
$(function () { $.ajax({ url: "http://localhost:8081/api/db/entity/user_data", type: "GET", data: { 'filter': [ { 'field': 'cycle', 'where': 'or', 'type': 'between', 'from': '1', 'to': '100' }, { 'field': 'cycle', 'where': 'or', 'type': 'gte', 'value': '1000' } ] }, dataType: "json" }); });
查询关系
单值
可以通过关系查询集合——只需提供关系名称作为fieldName
和标识符作为value
。
假设我们已定义了两个实体,User
和UserGroup
...
/** * @Entity */ class User { /** * @ManyToOne(targetEntity="UserGroup") * @var UserGroup */ protected $group; }
/** * @Entity */ class UserGroup {}
通过以下过滤器查询用户资源,找到属于UserGroup id #1的所有用户:
['type' => 'eq', 'field' => 'group', 'value' => '1']
集合值
要匹配集合中包含实体B的实体A,请使用ismemberof
。假设User
与UserGroup
有关联(多对多或一对多)...
/** * @Entity */ class User { /** * @ManyToMany(targetEntity="UserGroup") * @var UserGroup[]|ArrayCollection */ protected $groups; }
通过以下过滤器查询用户资源,找到属于UserGroup id #1的所有用户:
['type' => 'ismemberof', 'field' => 'groups', 'value' => '1']
日期字段格式
当日期字段参与过滤器时,您可以使用PHP日期格式化选项指定日期格式。默认日期格式是Y-m-d H:i:s
如果有一个日期字段,仅是Y-m-d
,那么在过滤器中添加该格式。有关完整的日期格式选项,请参阅DateTime::createFromFormat
[ 'format' => 'Y-m-d', 'value' => '2014-02-04', ]
连接实体和查询别名
包含了一个ORM查询类型用于内连接,因此对于每个过滤器类型,都有一个可选的alias
。默认别名为'row',它引用REST资源的核心实体。没有过滤器可以添加其他实体到返回数据中。也就是说,默认情况下,只有原始目标资源'row'会被返回,无论通过此模块应用了什么过滤器或排序。
内连接默认不包括在zf-doctrine-querybuilder.global.php.dist
中。
此示例通过行实体上已定义的内连接连接报告字段,然后过滤为r.id = 2
['type' => 'innerjoin', 'field' => 'report', 'alias' => 'r'], ['type' => 'eq', 'alias' => 'r', 'field' => 'id', 'value' => '2']
您可以使用parentAlias
从内连接中连接表
['type' => 'innerjoin', 'parentAlias' => 'r', 'field' => 'owner', 'alias' => 'o'],
内连接默认在zf-doctrine-querybuilder.global.php.dist
中注释。
还有一个ORM查询类型为LeftJoin。这种连接类型通常用于获取关系的空右侧。
LeftJoin默认在zf-doctrine-querybuilder.global.php.dist
中注释。
['type' => 'leftjoin', 'field' => 'report', 'alias' => 'r'], ['type' => 'isnull', 'alias' => 'r', 'field' => 'id']
包含的过滤器类型
ORM和ODM
等于
['type' => 'eq', 'field' => 'fieldName', 'value' => 'matchValue']
不等于
['type' => 'neq', 'field' => 'fieldName', 'value' => 'matchValue']
小于
['type' => 'lt', 'field' => 'fieldName', 'value' => 'matchValue']
小于等于
['type' => 'lte', 'field' => 'fieldName', 'value' => 'matchValue']
大于
['type' => 'gt', 'field' => 'fieldName', 'value' => 'matchValue']
大于等于
['type' => 'gte', 'field' => 'fieldName', 'value' => 'matchValue']
为空
['type' => 'isnull', 'field' => 'fieldName']
不为空
['type' => 'isnotnull', 'field' => 'fieldName']
注意:In和NotIn过滤器中的日期不是作为日期处理的。建议对于日期数据类型,您使用多个等于语句而不是这些过滤器。
In
['type' => 'in', 'field' => 'fieldName', 'values' => [1, 2, 3]]
不在
['type' => 'notin', 'field' => 'fieldName', 'values' => [1, 2, 3]]
介于
['type' => 'between', 'field' => 'fieldName', 'from' => 'startValue', 'to' => 'endValue']
类似(使用 %
作为通配符)
['type' => 'like', 'field' => 'fieldName', 'value' => 'like%search']
仅ORM
是成员
['type' => 'ismemberof', 'field' => 'fieldName', 'value' => 1]
并且X
在AndX查询中,conditions
是一个数组,包含此处描述的任何筛选类型。连接始终为 and
,所以条件中的 where
参数将被忽略。AndX筛选类型上的 where
参数不会被忽略。
[ 'type' => 'andx', 'conditions' => [ ['field' =>'name', 'type'=>'eq', 'value' => 'ArtistOne'], ['field' =>'name', 'type'=>'eq', 'value' => 'ArtistTwo'], ], 'where' => 'and', ]
或者X
在OrX查询中,conditions
是一个数组,包含此处描述的任何筛选类型。连接始终为 or
,所以条件中的 where
参数将被忽略。OrX筛选类型上的 where
参数不会被忽略。
[ 'type' => 'orx', 'conditions' => [ ['field' =>'name', 'type'=>'eq', 'value' => 'ArtistOne'], ['field' =>'name', 'type'=>'eq', 'value' => 'ArtistTwo'], ], 'where' => 'and', ]
仅ODM
正则表达式
['type' => 'regex', 'field' => 'fieldName', 'value' => '/.*search.*/i']
包含的排序类型
字段
['type' => 'field', 'field' => 'fieldName', 'direction' => 'desc']