API Platform custom collection filter on identifier
API Platform supports various filters out of the box, like the SearchFilter
. The filters though lack support for filtering on an entity's id when using another property as the identifier of the entity. Given you have for example the field ext_ref
marked as identifier of the entity, but you want the filter the end user of the API sets to use id as property to filter on that ext_ref
you thus need to write a custom filter. An example of such a custom filter is shown below.
<?php
use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Operation;
use Doctrine\ORM\QueryBuilder;
use InvalidArgumentException;
final class IdentifiersFilter extends AbstractFilter
{
const PROPERTY_NAME = 'ids';
protected function filterProperty($property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, $resourceClass, Operation $operation = null, $context = [])
{
$idFields = array_keys($this->getProperties());
if ($property !== self::PROPERTY_NAME) {
return;
}
$idField = $idFields[0];
$extRefs = [];
foreach ($value as $extRef) {
$extRefs[] = $extRef;
}
$alias = $queryBuilder->getRootAliases()[0];
$queryBuilder->andWhere(
$queryBuilder->expr()->in($alias.'.'.$idField, $extRefs)
);
}
public function getDescription(string $resourceClass): array
{
return [
self::PROPERTY_NAME => [
'property' => 'ext_ref',
'type' => 'iterable',
'required' => false,
'swagger' => [
'description' => 'Filter by id',
'name' => 'Id',
'type' => 'iterable',
],
],
];
}
}
Now you can apply the filter on your entity like so:
#[ApiFilter(IdentifiersFilter::class, properties: ['ext_ref'])]
Querying this entity thus now supports the ids filter allowing you to filter your collection by the ext_ref (while the user thus doesn't know that and passes along id as he/she expects).
query queryMyEntities {
myEntity(ids:["my-value1-thats-actually-the-ext-ref", "my-value2-thats-actually-the-ext-ref"]) {
totalCount
edges {
cursor
node {
ext_ref: id
name
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
See https://api-platform.com/docs/core/filters/#creating-custom-filters for more information.