我目前正在使用 API 平台及其默认的 SearchFilter,它按预期工作。
但是,由于 url 中的查询字符串很长,因此对资源之间的深层关系进行过滤可能会很繁重。 (我有多个这样的实体。)
例如,我想搜索特定国家/地区商店中列出的所有书籍:
{url}/books?department.store.city.country.name=italy
有没有办法编辑@ApiFilter(SearchFilter::class, properties={}) 以便在最后得到简单的?
{url}/books?country_filter=italy
谢谢!
答案 0 :(得分:0)
您可以创建一个自定义 api 过滤器并在其中添加您自己的逻辑。将其称为 country_filter 并仅传递一个值,之后自定义查询将在数据库中搜索并返回行。要制作一个,您必须扩展 AbstractFilter 类,然后您必须将此过滤器添加到您的实体中。来自官方网站的一个很好的教程是 here 和下一章 here
答案 1 :(得分:0)
谢谢您的建议,
经过一些(数小时的)研究,我得出的结论是在创建我的个人 CountryFilter 时扩展 SearchFilter :
在我的实体类中:
/*
* @ApiFilter(CountryFilter::class, properties={
* "country_filter": "department.store.city.country.name",
* })
*/
在我的 App\Filter\CountryFilter.php 中:
<?php
namespace App\Filter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractContextAwareFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use Doctrine\ORM\QueryBuilder;
final class CountryFilter extends SearchFilter
{
protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null)
{
foreach($this->properties as $alias => $propertyName){
if($alias == $property){
$property = $propertyName;
break;
}
}
/*
if (
null === $value ||
!$this->isPropertyEnabled($property, $resourceClass) ||
!$this->isPropertyMapped($property, $resourceClass, true)
) {
return;
}
*/
// The rest of the SearchFilter.php copy/pasted code ...
}
public function getDescription(string $resourceClass): array
{
// ....
}
}