Published on

Api platform 教程10---过滤

原创文章,转载时需取得本人同意并注明来源
Authors
  • Api platform 教程10---过滤
    Name
    langziyang
    Twitter

Api platform 教程10---过滤

现在我们基本能做一个CRUD了,一点问题都没有,但是客户现要要求在长达几千条数据中按条件过滤一些数据,很简单,Api platform 附带了一系列内置过滤器,允许您按文本、布尔值、日期等过滤结果集合。

它的工作原理如下:在类上方添加一个名为 ApiFilter 的属性。

通常,我们需要两个参数,第一个是过滤器类,然后是过滤字段名

假设我们想按Treasure的name字段过滤,这是一个string,所以我们用SearchFilter:

#[ApiFilter(SearchFilter::class, properties: ['name' => 'partial'])]
#[ApiFilter(BooleanFilter::class, properties: ['isPublished'])]
#[ApiFilter(DateFilter::class, properties: ['createdAt'])]
#[ApiFilter(RangeFilter::class, properties: ['value'])]
class DragonTreasure
{
    //...
}

properties我们开启了name字段,搜索支持exact, partial, start, end和word_start匹配策略。

  1. partial 策略使用 LIKE %text% 搜索包含 text 的字段。
  2. start 策略使用 LIKE text% 搜索以 text 开头的字段。
  3. end 策略使用 LIKE %text 搜索以 text 结尾的字段。
  4. word_start 策略使用 LIKE text% OR LIKE % text% 搜索包含以 text 开头的单词的字段。

如果您希望过滤器不区分大小写,请在过滤器前面添加字母 i 。例如 ipartial 或 iexact 。请注意,这将使用 LOWER 函数,如果没有正确的索引,将会影响性能。

除了SearchFilter,我还有开启了其它几种搜索,具体怎么用,有哪些参数,请查看文档。

这里还有一个问题:多表联查,如果你想取某个用户的宝藏,你还可以通过下面的方式:

#[ApiFilter(SearchFilter::class, properties: ['name' => 'partial','user.id'=>'exact','user.email'=>'partial'])]

这样就可以通过用户的id和email来搜索了。但是如果我们的搜索并不在Entity字段中又怎么办呢?

我们还可以extending api platform:

#src/ApiResource/Extensions/DragonTreasureCollectionExtension.php
<?php

namespace App\ApiResource\Extensions;

use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\CollectionOperationInterface;
use ApiPlatform\Metadata\Operation;
use App\Entity\DragonTreasure;
use Doctrine\ORM\QueryBuilder;

class DragonTreasureCollectionExtension implements QueryCollectionExtensionInterface
{

    public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, ?Operation $operation = null, array $context = []): void
    {
        if ($resourceClass !== DragonTreasure::class || !$operation instanceof CollectionOperationInterface) {
            return;
        }
        $rootAlias = $queryBuilder->getRootAliases()[0];

        $queryBuilder->andWhere(sprintf('%s.coolFactor=:coolFactor', $rootAlias))
            ->setParameter('coolFactor', 1);
    }
}

上面的代码添加了一个简单的查询条件,我相信你稍微看一看就能明白