api-skeletons/doctrine-querybuilder-filter

此包已弃用且不再维护。作者建议使用 API-Skeletons/doctrine-orm-querybuilder-filter 包。

使用 filter[fieldName|operator]=value 过滤 QueryBuilder

2.0.0 2022-04-18 06:51 UTC

This package is auto-updated.

Last update: 2023-10-21 14:21:42 UTC


README

Build Status Code Coverage PHP Version Total Downloads License

根据请求参数对 QueryBuilder 应用过滤器。支持使用连接进行深度查询。此仓库旨在将查询参数应用于筛选实体数据。

安装

运行以下命令使用 Composer 安装此库

composer require api-skeletons/doctrine-querybuilder-filter

快速入门

use ApiSkeletons\Doctrine\QueryBuilder\Filter\Applicator;

$applicator = new Applicator($entityManager, Entity\User::class);
$queryBuilder = $applicator($_REQUEST['filter']);

过滤器

创建过滤器的模式是 filter[fieldName|operator]=value 这种模式是一种简单的方法,可以定义利用 QueryBuilder 所有过滤功能的复杂查询。

以下 URL 将提供对用户 name 的 LIKE 过滤器

http://localhost/api/user?filter[name|like]=John

支持的运算符

  • eq - 等于。如果没有指定运算符,则默认为此运算符
  • neq - 不等于
  • gt - 大于
  • gte - 大于等于
  • lt - 小于
  • lte - 小于等于
  • between - 在两个值之间,用逗号分隔,例如 filter[id|between]=1,5
  • like - 模糊搜索,用通配符包裹值
  • startswith - 带有右边通配符的 like 运算符
  • endswith - 带有左边通配符的 like 运算符
  • in - 要匹配的值列表,用逗号分隔,例如 filter[id|in]=1,2,3]
  • notin - 与 in 运算符相反
  • isnull - 任何值都接受;将检查字段是否为 null
  • isnotnull - 与 isNull 运算符相反
  • sort - 按字段对结果进行排序,可以是 ascdesc

您可以使用任意数量的过滤器。过滤器作用于实体字段名和关联名。这允许您对关联进行筛选。例如,要按公司 ID 和正确的 Doctrine 元数据筛选用户列表,您可以按如下方式筛选

http://localhost/api/user?filter[company]=10

因此,即使没有名为公司的字段,也存在一个关联,并且可以通过此工具进行筛选。

对单个实体进行筛选

Applicator 的配置允许您启用关联筛选,但默认情况下是禁用的。因此,假设默认设置,这是对单个实体的复杂筛选

http://localhost/api/user?filter[company|neq]=15&filter[name]=John

对实体层次结构进行筛选

Applicator 的配置允许您启用关联筛选。这意味着您可以根据与当前实体关联的字段筛选当前实体,并且可以深入到您想要的程度。

在此示例中,我们将根据用户的公司名称检索用户数据

http://localhost/api/user?filter[company][name|eq]=AAA

在此示例中,我们将根据公司的公司类型和公司类型名称检索用户数据

http://localhost/api/user?filter[company][companyType][name|neq]=Consultant

在您过于担心此功能之前,请记住您可以在应用过滤器之后修改 QueryBuilder,因此如果您需要应用安全设置,这是支持的。

关于排序的说明

虽然排序在严格的定义上不是筛选,但在请求数据时它属于同一上下文。您可以根据多个字段进行排序,并且可以跨关联(如果启用)进行排序。排序是按照从左到右的顺序优先的。

使用

这是使用此库所需的最小配置。

use ApiSkeletons\Doctrine\QueryBuilder\Filter\Applicator;

$applicator = (new Applicator($entityManager, Entity\User::class));
$queryBuilder = $applicator($_REQUEST['filter']);

这是一个配置应用器的示例,使用了所有可能的选项。

use ApiSkeletons\Doctrine\QueryBuilder\Filter\Applicator;

$applicator = (new Applicator($entityManager, Entity\User::class))
    ->enableRelationships()
    ->removeOperator('like')
    ->setEntityAlias('user')
    ->setFieldAliases(['firstName' => 'name'])
    ->setFilterableFields(['id', 'name'])
    ;
$queryBuilder = $applicator($_REQUEST['filter']);

$entityAliasMap = $applicator->getEntityAliasMap();

在将过滤器应用到查询构建器并返回后,您可以在使用它来获取结果之前按需修改它。

真实世界Laravel示例

在这个例子中,使用HAL在控制器操作中以分页响应返回了来自 Entity\Style 实体的数据。[HAL](https://github.com/API-Skeletons/laravel-hal "HAL")

use ApiSkeletons\Doctrine\QueryBuilder\Filter\Applicator;
use Doctrine\ORM\Tools\Pagination\Paginator;
use HAL;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;


public function fetchAll(Request $request)
{
    $filter = $request->query()['filter'] ?? [];
    if (! is_array($filter)) {
        $filter = [];
    ]
    
    $page = (int) $request->query()['page'] ?? 1;
    if ($page < 1) {
        $page = 1;
    }

    $applicator = (new Applicator(app('em'), Entity\Style::class))
        ->enableRelationships(true);
    $queryBuilder = $applicator($filter);

    $paginator = new Paginator($queryBuilder);
    $paginator->getQuery()
        ->setFirstResult(25 * ($page - 1)) // Page is 0 indexed in query
        ->setMaxResults(25)
        ;

    $data = (new LengthAwarePaginator(iterator_to_array($paginator->getIterator()), $paginator->count(), 25))
        ->appends($request->query())
        ->withPath(route('api.style::fetchAll'))
        ;

    return HAL::paginate('style', $data)->toArray();
}

配置

使用应用器非常简单,有许多配置选项。首先创建应用器,然后运行配置函数。

$applicator = new Applicator($entityManager, Entity\Style::class);

enableAssociations()

此配置方法通过使用Doctrine元数据遍历ORM,通过现有连接到目标实体的连接来启用深度过滤。这仅在具有完整元数据和在元数据中定义的实体之间正确关联的Doctrine安装中才可行。

removeOperator(string|array)

如果您想禁用任何操作符,可以将其删除。一个好的例子是 like 操作符,它可能会导致昂贵的查询。

setEntityAlias(string)

在创建针对目标实体的过滤器时,默认使用的别名是 entity。您可能希望更改此别名,以便在查询构建器返回后知道别名,并向它添加额外的参数。

setFieldAliases(array)

如果您想使过滤器使用别名而不是使用ORM字段名称(例如在 hydrators 中使用命名策略),您可以传递一个 [alias => field] 的值数组,以便调整映射。

setFilterableFields(array)

默认情况下,可以过滤目标实体上的所有字段。如果您想限制用户可以创建过滤器的字段,请将那些字段名称传递到该数组中。

getEntityAliasMap()

此方法用于目标实体的后处理。当用户使用 enableAssociations() 进行深度过滤时,将为每个连接到原始实体查询的实体创建别名。此方法返回一个包含 [alias => entityClass] 的数组,其中包含在查询构建器中连接的所有实体。