Guides
Tutorials
The search filter allows to filter a collection by given properties.
The search filter supports exact, partial, start, end, and word_start matching strategies:
exact strategy searches for fields that exactly match the valuepartial strategy uses LIKE %value% to search for fields that contain the valuestart strategy uses LIKE value% to search for fields that start with the valueend strategy uses LIKE %value to search for fields that end with the valueword_start strategy uses LIKE value% OR LIKE % value% to search for fields that contain words starting with the valueNote: it is possible to filter on properties and relations too.
Prepend the letter i to the filter if you want it to be case-insensitive. For example ipartial or iexact.
Note that this will use the LOWER function and will impact performance if there is no proper index.
Case insensitivity may already be enforced at the database level depending on the collation used.
If you are using MySQL, note that the commonly used utf8_unicode_ci collation (and its sibling utf8mb4_unicode_ci)
are already case-insensitive, as indicated by the _ci part in their names.
Note: Search filters with the exact strategy can have multiple values for the same property (in this case the
condition will be similar to a SQL IN clause).
Syntax: ?property[]=foo&property[]=bar.
<?php
// api/src/Entity/Book.php
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
#[ApiResource]
#[ApiFilter(SearchFilter::class, properties: ['isbn' => 'exact', 'description' => 'partial'])]
class Book
{
// ...
}<?php
// api/src/Entity/Book.php
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
#[ApiResource]
#[ApiFilter(SearchFilter::class, properties: ['isbn' => 'exact', 'description' => 'partial'])]
class Book
{
// ...
}# config/services.yaml
services:
book.search_filter:
parent: 'api_platform.doctrine.orm.search_filter'
arguments: [ { isbn: 'exact', description: 'partial' } ]
tags: [ 'api_platform.filter' ]
# The following are mandatory only if a _defaults section is defined with inverted values.
# You may want to isolate filters in a dedicated file to avoid adding the following lines (by adding them in the defaults section)
autowire: false
autoconfigure: false
public: false
# api/config/api_platform/resources.yaml
resources:
App\Entity\Book:
- operations:
ApiPlatform\Metadata\GetCollection:
filters: ['book.search_filter']# config/services.yaml
services:
book.search_filter:
parent: 'api_platform.doctrine.orm.search_filter'
arguments: [ { isbn: 'exact', description: 'partial' } ]
tags: [ 'api_platform.filter' ]
# The following are mandatory only if a _defaults section is defined with inverted values.
# You may want to isolate filters in a dedicated file to avoid adding the following lines (by adding them in the defaults section)
autowire: false
autoconfigure: false
public: false
# api/config/api_platform/resources.yaml
resources:
App\Entity\Book:
- operations:
ApiPlatform\Metadata\GetCollection:
filters: ['book.search_filter']<?xml version="1.0" encoding="UTF-8" ?>
<!-- api/config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container
xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="book.search_filter" parent="api_platform.doctrine.orm.search_filter">
<argument type="collection">
<argument key="isbn">exact</argument>
<argument key="description">partial</argument>
</argument>
<tag name="api_platform.filter"/>
</service>
</services>
</container>
<!-- api/config/api_platform/resources.xml -->
<resources
xmlns="https://api-platform.com/schema/metadata/resources-3.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://api-platform.com/schema/metadata/resources-3.0
https://api-platform.com/schema/metadata/resources-3.0.xsd">
<resource class="App\Entity\Book">
<operations>
<operation class="ApiPlatform\Metadata\GetCollection">
<filters>
<filter>book.search_filter</filter>
</filters>
</operation>
</operations>
</resource>
</resources><?xml version="1.0" encoding="UTF-8" ?>
<!-- api/config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container
xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="book.search_filter" parent="api_platform.doctrine.orm.search_filter">
<argument type="collection">
<argument key="isbn">exact</argument>
<argument key="description">partial</argument>
</argument>
<tag name="api_platform.filter"/>
</service>
</services>
</container>
<!-- api/config/api_platform/resources.xml -->
<resources
xmlns="https://api-platform.com/schema/metadata/resources-3.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://api-platform.com/schema/metadata/resources-3.0
https://api-platform.com/schema/metadata/resources-3.0.xsd">
<resource class="App\Entity\Book">
<operations>
<operation class="ApiPlatform\Metadata\GetCollection">
<filters>
<filter>book.search_filter</filter>
</filters>
</operation>
</operations>
</resource>
</resources>class ApiPlatform\Doctrine\Orm\Filter\SearchFilter extends ApiPlatform\Doctrine\Orm\Filter\AbstractFilter implements `<a href="/docs/reference/Doctrine/Orm/Filter/FilterInterface">ApiPlatform\Doctrine\Orm\Filter\FilterInterface</a>`, `<a href="/docs/reference/Metadata/FilterInterface">ApiPlatform\Metadata\FilterInterface</a>`, `<a href="/docs/reference/Doctrine/Common/Filter/SearchFilterInterface">ApiPlatform\Doctrine\Common\Filter\SearchFilterInterface</a>`
{
public __construct(Doctrine\Persistence\ManagerRegistry $managerRegistry, ApiPlatform\Api\IriConverterInterface $iriConverter, null|Symfony\Component\PropertyAccess\PropertyAccessorInterface $propertyAccessor, null|Psr\Log\LoggerInterface $logger, null|array $properties, null|ApiPlatform\Api\IdentifiersExtractorInterface $identifiersExtractor, null|Symfony\Component\Serializer\NameConverter\NameConverterInterface $nameConverter)
protected getIriConverter(): ApiPlatform\Api\IriConverterInterface
protected getPropertyAccessor(): Symfony\Component\PropertyAccess\PropertyAccessorInterface
protected filterProperty(string $property, $value, Doctrine\ORM\QueryBuilder $queryBuilder, ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, null|ApiPlatform\Metadata\Operation $operation, array $context): null
protected addWhereByStrategy(string $strategy, Doctrine\ORM\QueryBuilder $queryBuilder, ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface $queryNameGenerator, string $alias, string $field, $values, bool $caseSensitive): null
protected createWrapCase(bool $caseSensitive): Closure
protected getType(string $doctrineType): string
public apply(Doctrine\ORM\QueryBuilder $queryBuilder, ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, null|ApiPlatform\Metadata\Operation $operation, array $context): null
protected getManagerRegistry(): Doctrine\Persistence\ManagerRegistry
protected getProperties(): array
protected getLogger(): Psr\Log\LoggerInterface
protected isPropertyEnabled(string $property, string $resourceClass): bool
protected denormalizePropertyName(string|int $property): string
protected normalizePropertyName(string $property): string
protected splitPropertyParts(string $property, string $resourceClass): array
protected addJoinsForNestedProperty(string $property, string $rootAlias, Doctrine\ORM\QueryBuilder $queryBuilder, ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $joinType): array
protected isPropertyMapped(string $property, string $resourceClass, bool $allowAssociation): bool
protected isPropertyNested(string $property, string $resourceClass): bool
protected isPropertyEmbedded(string $property, string $resourceClass): bool
protected getDoctrineFieldType(string $property, string $resourceClass): string
protected getNestedMetadata(string $resourceClass, array<int, string> $associations): Doctrine\Persistence\Mapping\ClassMetadata
protected getClassMetadata(string $resourceClass): Doctrine\Persistence\Mapping\ClassMetadata
public getDescription(string $resourceClass): array
protected getIdFromValue(string $value)
protected normalizeValues(array $values, string $property): array
protected hasValidValues(array $values, null|string $type): bool
}class ApiPlatform\Doctrine\Orm\Filter\SearchFilter extends ApiPlatform\Doctrine\Orm\Filter\AbstractFilter implements `<a href="/docs/reference/Doctrine/Orm/Filter/FilterInterface">ApiPlatform\Doctrine\Orm\Filter\FilterInterface</a>`, `<a href="/docs/reference/Metadata/FilterInterface">ApiPlatform\Metadata\FilterInterface</a>`, `<a href="/docs/reference/Doctrine/Common/Filter/SearchFilterInterface">ApiPlatform\Doctrine\Common\Filter\SearchFilterInterface</a>`
{
public __construct(Doctrine\Persistence\ManagerRegistry $managerRegistry, ApiPlatform\Api\IriConverterInterface $iriConverter, null|Symfony\Component\PropertyAccess\PropertyAccessorInterface $propertyAccessor, null|Psr\Log\LoggerInterface $logger, null|array $properties, null|ApiPlatform\Api\IdentifiersExtractorInterface $identifiersExtractor, null|Symfony\Component\Serializer\NameConverter\NameConverterInterface $nameConverter)
protected getIriConverter(): ApiPlatform\Api\IriConverterInterface
protected getPropertyAccessor(): Symfony\Component\PropertyAccess\PropertyAccessorInterface
protected filterProperty(string $property, $value, Doctrine\ORM\QueryBuilder $queryBuilder, ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, null|ApiPlatform\Metadata\Operation $operation, array $context): null
protected addWhereByStrategy(string $strategy, Doctrine\ORM\QueryBuilder $queryBuilder, ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface $queryNameGenerator, string $alias, string $field, $values, bool $caseSensitive): null
protected createWrapCase(bool $caseSensitive): Closure
protected getType(string $doctrineType): string
public apply(Doctrine\ORM\QueryBuilder $queryBuilder, ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, null|ApiPlatform\Metadata\Operation $operation, array $context): null
protected getManagerRegistry(): Doctrine\Persistence\ManagerRegistry
protected getProperties(): array
protected getLogger(): Psr\Log\LoggerInterface
protected isPropertyEnabled(string $property, string $resourceClass): bool
protected denormalizePropertyName(string|int $property): string
protected normalizePropertyName(string $property): string
protected splitPropertyParts(string $property, string $resourceClass): array
protected addJoinsForNestedProperty(string $property, string $rootAlias, Doctrine\ORM\QueryBuilder $queryBuilder, ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $joinType): array
protected isPropertyMapped(string $property, string $resourceClass, bool $allowAssociation): bool
protected isPropertyNested(string $property, string $resourceClass): bool
protected isPropertyEmbedded(string $property, string $resourceClass): bool
protected getDoctrineFieldType(string $property, string $resourceClass): string
protected getNestedMetadata(string $resourceClass, array<int, string> $associations): Doctrine\Persistence\Mapping\ClassMetadata
protected getClassMetadata(string $resourceClass): Doctrine\Persistence\Mapping\ClassMetadata
public getDescription(string $resourceClass): array
protected getIdFromValue(string $value)
protected normalizeValues(array $values, string $property): array
protected hasValidValues(array $values, null|string $type): bool
}Psr\Log\LoggerInterface $loggerPsr\Log\LoggerInterface $loggerDoctrine\Persistence\ManagerRegistry $managerRegistryDoctrine\Persistence\ManagerRegistry $managerRegistryarray $propertiesarray $propertiesSymfony\Component\Serializer\NameConverter\NameConverterInterface $nameConverterSymfony\Component\Serializer\NameConverter\NameConverterInterface $nameConverterApiPlatform\Api\IriConverterInterface $iriConverterApiPlatform\Api\IriConverterInterface $iriConverterSymfony\Component\PropertyAccess\PropertyAccessorInterface $propertyAccessorSymfony\Component\PropertyAccess\PropertyAccessorInterface $propertyAccessorApiPlatform\Api\IdentifiersExtractorInterface $identifiersExtractorApiPlatform\Api\IdentifiersExtractorInterface $identifiersExtractorpublic __construct(Doctrine\Persistence\ManagerRegistry $managerRegistry, ApiPlatform\Api\IriConverterInterface $iriConverter, null|Symfony\Component\PropertyAccess\PropertyAccessorInterface $propertyAccessor, null|Psr\Log\LoggerInterface $logger, null|array $properties, null|ApiPlatform\Api\IdentifiersExtractorInterface $identifiersExtractor, null|Symfony\Component\Serializer\NameConverter\NameConverterInterface $nameConverter)public __construct(Doctrine\Persistence\ManagerRegistry $managerRegistry, ApiPlatform\Api\IriConverterInterface $iriConverter, null|Symfony\Component\PropertyAccess\PropertyAccessorInterface $propertyAccessor, null|Psr\Log\LoggerInterface $logger, null|array $properties, null|ApiPlatform\Api\IdentifiersExtractorInterface $identifiersExtractor, null|Symfony\Component\Serializer\NameConverter\NameConverterInterface $nameConverter)| managerRegistry | Doctrine\Persistence\ManagerRegistry | |
| iriConverter | ApiPlatform\Api\IriConverterInterface | |
| propertyAccessor | Symfony\Component\PropertyAccess\PropertyAccessorInterface | |
| logger | Psr\Log\LoggerInterface | |
| properties | array | |
| identifiersExtractor | ApiPlatform\Api\IdentifiersExtractorInterface | |
| nameConverter | Symfony\Component\Serializer\NameConverter\NameConverterInterface |
protected getIriConverter(): ApiPlatform\Api\IriConverterInterfaceprotected getIriConverter(): ApiPlatform\Api\IriConverterInterfaceApiPlatform\Api\IriConverterInterface
protected getPropertyAccessor(): Symfony\Component\PropertyAccess\PropertyAccessorInterfaceprotected getPropertyAccessor(): Symfony\Component\PropertyAccess\PropertyAccessorInterfaceSymfony\Component\PropertyAccess\PropertyAccessorInterface
Passes a property through the filter.
protected filterProperty(string $property, $value, Doctrine\ORM\QueryBuilder $queryBuilder, ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, null|ApiPlatform\Metadata\Operation $operation, array $context): nullprotected filterProperty(string $property, $value, Doctrine\ORM\QueryBuilder $queryBuilder, ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, null|ApiPlatform\Metadata\Operation $operation, array $context): null| property | string | |
| value | ||
| queryBuilder | Doctrine\ORM\QueryBuilder | |
| queryNameGenerator | ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface | |
| resourceClass | string | |
| operation | ApiPlatform\Metadata\Operation | |
| context | array |
null
Adds where clause according to the strategy.
protected addWhereByStrategy(string $strategy, Doctrine\ORM\QueryBuilder $queryBuilder, ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface $queryNameGenerator, string $alias, string $field, $values, bool $caseSensitive): nullprotected addWhereByStrategy(string $strategy, Doctrine\ORM\QueryBuilder $queryBuilder, ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface $queryNameGenerator, string $alias, string $field, $values, bool $caseSensitive): null| strategy | string | |
| queryBuilder | Doctrine\ORM\QueryBuilder | |
| queryNameGenerator | ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface | |
| alias | string | |
| field | string | |
| values | ||
| caseSensitive | bool |
null
Creates a function that will wrap a Doctrine expression according to the specified case sensitivity.For example, "o.name" will get wrapped into "LOWER(o.name)" when $caseSensitive is false.
protected createWrapCase(bool $caseSensitive): Closureprotected createWrapCase(bool $caseSensitive): Closure| caseSensitive | bool |
Closure
protected getType(string $doctrineType): stringprotected getType(string $doctrineType): string| doctrineType | string |
string
Splits the given property into parts.Returns an array with the following keys:
protected splitPropertyParts(string $property, string $resourceClass): arrayprotected splitPropertyParts(string $property, string $resourceClass): array| property | string | |
| resourceClass | string |
array
Determines whether the given property is mapped.
protected isPropertyMapped(string $property, string $resourceClass, bool $allowAssociation): boolprotected isPropertyMapped(string $property, string $resourceClass, bool $allowAssociation): bool| property | string | |
| resourceClass | string | |
| allowAssociation | bool |
bool
Determines whether the given property is nested.
protected isPropertyNested(string $property, string $resourceClass): boolprotected isPropertyNested(string $property, string $resourceClass): bool| property | string | |
| resourceClass | string |
bool
Determines whether the given property is embedded.
protected isPropertyEmbedded(string $property, string $resourceClass): boolprotected isPropertyEmbedded(string $property, string $resourceClass): bool| property | string | |
| resourceClass | string |
bool
Gets the Doctrine Type of a given property/resourceClass.
protected getDoctrineFieldType(string $property, string $resourceClass): stringprotected getDoctrineFieldType(string $property, string $resourceClass): string| property | string | |
| resourceClass | string |
string
Gets nested class metadata for the given resource.
protected getNestedMetadata(string $resourceClass, array<int, string> $associations): Doctrine\Persistence\Mapping\ClassMetadataprotected getNestedMetadata(string $resourceClass, array<int, string> $associations): Doctrine\Persistence\Mapping\ClassMetadata| resourceClass | string | |
| associations | array<int, string> |
Doctrine\Persistence\Mapping\ClassMetadata
Gets class metadata for the given resource.
protected getClassMetadata(string $resourceClass): Doctrine\Persistence\Mapping\ClassMetadataprotected getClassMetadata(string $resourceClass): Doctrine\Persistence\Mapping\ClassMetadata| resourceClass | string |
Doctrine\Persistence\Mapping\ClassMetadata
Gets the description of this filter for the given resource.Returns an array with the filter parameter names as keys and array with the following data as values:
public getDescription(string $resourceClass): arraypublic getDescription(string $resourceClass): array| resourceClass | string |
array
Gets the ID from an IRI or a raw ID.
protected getIdFromValue(string $value)protected getIdFromValue(string $value)| value | string |
Normalize the values array.
protected normalizeValues(array $values, string $property): arrayprotected normalizeValues(array $values, string $property): array| values | array | |
| property | string |
array
When the field should be an integer, check that the given value is a valid one.
protected hasValidValues(array $values, null|string $type): boolprotected hasValidValues(array $values, null|string $type): bool| values | array | |
| type | string |
bool