php - 如何在 Api-Platform 中为虚拟属性引入过滤功能?
问题描述
我正在使用 Symfony 5 和 API 平台。
我的一个类有一个通过postLoad
监听器设置的属性。该属性仅在某些条件下设置(否则为NULL
),我希望允许 REST API 用户根据此属性是否为 null 或具有值来过滤资源。
因为虚拟属性没有持久化到数据库中,我假设没有任何 Doctrine 过滤器,例如ExistsFilter
,将在这个属性上工作。
如何使用 Symfony 5 和 API 平台为虚拟属性创建过滤功能?
解决方案
您可以创建自己的自定义 ORM 过滤器。
一个非常简单的例子来展示它是如何完成的:
假设一个类:
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 文档中找到。
推荐阅读
- logic - 如何将 Coq 用作计算器或前向链接规则引擎/序列应用工具?
- woocommerce - 从 Woocommerce 电子邮件通知中隐藏重力形式字段标签
- python - 如何在 Windows 10 上沙箱学生的 Python 3 代码提交以进行自动作业评估?
- c# - 如何在没有互联网的情况下在树莓派上包含 nuget 包?
- ruby-on-rails - 无法将 Ruby gem Gibbon 与 MailChimp API 链接起来
- javascript - 如何使用来自服务器的 FCM 向用户发送推送通知?
- julia - 如何在for循环中更改变量的名称
- actions-on-google - 为智能家居操作启用测试/模拟器时,“我们很抱歉,出了点问题,请重试”
- php - 如何修复 Laravel 电子邮件问题
- javascript - 隐藏 div 仅在 Ajax 响应的所有内容都已呈现后