如何在 Api-Platform 中为虚拟属性引入过滤功能?
Posted
技术标签:
【中文标题】如何在 Api-Platform 中为虚拟属性引入过滤功能?【英文标题】:How can I introduce filtering functionality for a virtual property in Api-Platform? 【发布时间】:2021-09-30 11:55:53 【问题描述】:我正在使用 Symfony 5 和 API 平台。
我的一个类有一个通过postLoad
监听器设置的属性。该属性仅在某些条件下设置(否则为NULL
),我想允许REST API用户根据该属性是否为空或有值来过滤资源。
因为虚拟属性没有持久化到数据库中,我假设没有 Doctrine 过滤器,例如ExistsFilter
将在此属性上工作。
如何使用 Symfony 5 和 API 平台为虚拟属性创建过滤功能?
【问题讨论】:
我认为这并不容易。只是好奇:您为实体设置了什么样的属性,但没有持久化?为什么不能持久化? 你看过custom data providers吗? 感谢您的 cmets,是的,我正在考虑使用自定义数据提供程序,但我很难理解事物的分页方面。我是否需要创建一个自定义分页器来对(以某种方式过滤的)资源集进行分页并在 getCollection() 中返回这个分页器? 【参考方案1】:您可以创建自己的custom ORM filters。
一个非常简单的例子来展示它是如何完成的:
假设一个类:
Foo
public int $weight;
public function isHeavy(): bool
return $this->weight > 40;
由于heavy
是“虚拟”属性,您无法直接对其进行过滤。
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractContextAwareFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use Doctrine\ORM\QueryBuilder;
class HeavyFilter extends AbstractContextAwareFilter
public function getDescription(string $resourceClass): array
// I'm making the filter available only
if (Foo::class !== $resourceClass)
return [];
if (!$this->properties)
return [];
$description = [];
$description['heavySearch'] =
[
'property' => 'heavy',
'type' => 'bool',
'required' => false,
'swagger' => [
'description' => 'Search for heavy foos',
'name' => 'Heavey Search',
'type' => 'bool',
],
];
return $description;
protected function filterProperty(
string $property,
$value,
QueryBuilder $queryBuilder,
QueryNameGeneratorInterface $queryNameGenerator,
string $resourceClass,
string $operationName = null
): void
if ('heavySearch' !== $property)
return;
if ($value === true)
$queryBuilder
->andWhere('o.weigth > 40');
else
$queryBuilder
->andWhere('o.weight <= 40');
还没有实际测试过,只是在这里写的,但基本想法是正确的。您需要根据自己的情况进行调整,并且您将拥有一个自定义过滤器,该过滤器甚至可以在 Open Api 文档中找到。
【讨论】:
嗨 yivi,非常感谢您的评论。我的应用程序中的虚拟属性不是映射的 Doctrine 字段,因此 queryBuilder 返回一个 QueryException 表示该类没有这样的字段或关联。以上是关于如何在 Api-Platform 中为虚拟属性引入过滤功能?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 api-platform 构建 GraphQL API?