问题描述
我正在使用 Symfony 5 和 API 平台。
我的一个类通过 postLoad
侦听器设置了它的一个属性。该属性仅在特定条件下设置(否则为 NULL
),我希望允许 REST API 用户根据此属性是否为 null 或是否有值来过滤资源。
因为虚拟属性没有持久化到数据库中,所以我假设没有 Doctrine 过滤器,例如ExistsFilter
将适用于此属性。
如何使用 Symfony 5 和 API 平台为虚拟资产创建过滤功能?
解决方法
您可以创建自己的 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 文档中使用自定义过滤器。