Api platform custom filters
When not using entities as the api resources, in order to filter collections one or more custom filters can be applied to the classes annotated with the [#ApiResource]
attribute.
Define a class as an ApiResource
and annotate it with the desired filter(s), using the [#ApiFilter]
attribute:
// src/ApiResource/ProductResource.php
<?php
declare(strict_types=1);
namespace App\ApiResource;
use App\Filter\ProductInStockFilter;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiResource;
[#ApiResource()]
[#ApiFilter(ProductInStockFilter::class)]
final class ProductResource
The custom filters should implement the \ApiPlatform\Serializer\Filter\FilterInterface
<?php
declare(strict_types=1);
namespace App\Filter;
use Symfony\Component\HttpFoundation\Request;
use ApiPlatform\Serializer\Filter\FilterInterface;
final class ProductInStockFilter implements FilterInterface
{
// This function adds the filter context, available in the api resource providers
public function apply(Request $request, bool $normalization, array $attributes, array &$context): void
{
$productInStock = $request->query->get('product_in_stock');
if (!$productInStock) {
return;
}
$context['product_in_stock'] = $productInStock;
}
// This function is only used to hook in documentation generators (supported by Swagger and Hydra)
public function getDescription(string $resourceClass): array
{
return [
'product_in_stock' => [
'property' => null,
'type' => 'string',
'required' => false,
],
];
}
}
The provider defined for the ProductResource
class will now have access to the filters within the $context
argument of the provide
method and these can be used when filtering the collection, in your repository for example:
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
if ($operation instanceof CollectionOperationInterface) {
// e.g. $context['filters']['product_in_stock'] = 1
if (isset($context['filters'])) {
$collection = $this->productRepository->filterBy($context['filters']);
} else {
$collection = $this->productRepository->findAll();
}
// transform your collection to your api resource and return
return $collection;
}
}
Read other posts