jackdpeterson / psr7-doctrine-querybuilder
PSR-7 Doctrine QueryBuilder模块 -- 使用PSR-7请求的$args操作Doctrine Query Builder实例
Requires
- php: ^5.6 || ^7.0
- doctrine/doctrine-module: ^1.2
- zendframework/zend-hydrator: ^1.1 || ^2.2.1
- zendframework/zend-modulemanager: ^2.7.2
- zendframework/zend-mvc: ^2.7.10 || ^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
- doctrine/doctrine-orm-module: ^1.1
- phpunit/phpunit: ^5.6
- 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: ^0.11, if you wish to use the Doctrine ODM
- doctrine/doctrine-orm-module: ^1.1, if you wish to use the Doctrine ORM
- ext/mongo: Mongo extension, if using ODM
README
此库提供从数组参数中查询构建器指令。此库旨在将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 jackdpeterson/psr7-doctrine-querybuilder
安装后,将jackdpeterson\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的别名列表以启用默认值。
与Slim框架一起使用
要启用所有过滤器,您可以覆盖默认的查询提供者在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' => \jackdpeterson\Doctrine\QueryBuilder\Query\Provider\DefaultOrm::class, 'default_odm' => \jackdpeterson\Doctrine\QueryBuilder\Query\Provider\DefaultOdm::class, ], 'factories' => [ \jackdpeterson\Doctrine\QueryBuilder\Query\Provider\DefaultOrm::class => \jackdpeterson\Doctrine\QueryBuilder\Query\Provider\DefaultOrmFactory::class, \jackdpeterson\Doctrine\QueryBuilder\Query\Provider\DefaultOdm::class => \jackdpeterson\Doctrine\QueryBuilder\Query\Provider\DefaultOdmFactory::class, ], ],
使用
配置示例
'zf-doctrine-querybuilder-orderby-orm' => [ 'aliases' => [ 'field' => \jackdpeterson\Doctrine\QueryBuilder\OrderBy\ORM\Field::class, ], 'factories' => [ \jackdpeterson\Doctrine\QueryBuilder\OrderBy\ORM\Field::class => \Zend\ServiceManager\Factory\InvokableFactory::class, ], ], 'zf-doctrine-querybuilder-filter-orm' => [ 'aliases' => [ 'eq' => \jackdpeterson\Doctrine\QueryBuilder\Filter\ORM\Equals::class, ], 'factories' => [ \jackdpeterson\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: "https://: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
。
假设我们已定义了2个实体,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-filter-orm' => [ 'aliases' => [ 'innerjoin' => \jackdpeterson\Doctrine\QueryBuilder\Filter\ORM\InnerJoin::class, ], 'factories' => [ \jackdpeterson\Doctrine\QueryBuilder\Filter\ORM\InnerJoin => \Zend\ServiceManager\Factory\InvokableFactory::class, ], ],
包含的过滤器类型
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过滤器中,日期被视为非日期。建议您对于日期数据类型,使用多个Equals语句而不是这些过滤器。
In
['type' => 'in', 'field' => 'fieldName', 'values' => [1, 2, 3]]
NotIn
['type' => 'notin', 'field' => 'fieldName', 'values' => [1, 2, 3]]
Between
['type' => 'between', 'field' => 'fieldName', 'from' => 'startValue', 'to' => 'endValue']
Like(使用%
作为通配符)
['type' => 'like', 'field' => 'fieldName', 'value' => 'like%search']
ORM 仅
是成员
['type' => 'ismemberof', 'field' => 'fieldName', 'value' => 1]
AndX
在AndX查询中,conditions
是这里描述的任何过滤器类型的数组。连接始终是and
,所以where
参数在conditions
内部被忽略。AndX过滤器类型上的where
参数不会被忽略。
[ 'type' => 'andx', 'conditions' => [ ['field' =>'name', 'type'=>'eq', 'value' => 'ArtistOne'], ['field' =>'name', 'type'=>'eq', 'value' => 'ArtistTwo'], ], 'where' => 'and', ]
OrX
在OrX查询中,conditions
是这里描述的任何过滤器类型的数组。连接始终是or
,所以where
参数在conditions
内部被忽略。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']