API Platform is great for Rapid Application Development and provides lots of functionalities out of the box such as collection filtering with Eloquent. Most of the filtering is done using query parameters, which are automatically documented and validated. If needed you can use state providers or a [Links Handler] to provide data.
A filter is usually used via a ApiPlatform\Metadata\QueryParameter and is also available through ApiPlatform\Metadata\HeaderParameter. For example, let’s declare an EqualsFilter on our Book to be able to query an exact match using /books?name=Animal Farm. A Fairy Story:
// app/Models/Book.php
use ApiPlatform\Laravel\Eloquent\Filter\EqualsFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\QueryParameter;
#[ApiResource]
#[QueryParameter(key: 'name', filter: EqualsFilter::class)]
class Book extends Model
{
}The key option specifies the query parameter and the filter applies the given value to a where clause:
namespace ApiPlatform\Laravel\Eloquent\Filter;
use ApiPlatform\Metadata\Parameter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
final class EqualsFilter implements FilterInterface
{
/**
* @param Builder<Model> $builder
* @param array<string, mixed> $context
*/
public function apply(Builder $builder, mixed $values, Parameter $parameter, array $context = []): Builder
{
return $builder->where($parameter->getProperty(), $values);
}
}You can create your own filters by implementing the ApiPlatform\Laravel\Eloquent\Filter\FilterInterface. API Platform provides several eloquent filters for a RAD approach.
To defines a parameter for only a GetCollection operation, you can do the following:
// app/Models/Book.php
use ApiPlatform\Laravel\Eloquent\Filter\EqualsFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\QueryParameter;
#[ApiResource]
#[GetCollection(parameters: ['name' => new QueryParameter(key: 'name', filter: EqualsFilter::class)])]
class Book extends Model
{
}You can add validation rules to parameters within the constraints attribute:
// app/Models/Book.php
use ApiPlatform\Laravel\Eloquent\Filter\PartialSearchFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\QueryParameter;
#[ApiResource]
#[QueryParameter(key: 'name', filter: PartialSearchFilter::class, constraints: 'min:2')]
class Book extends Model
{
}:property PlaceholderWhen programming APIs you may need to apply a filter on many properties at once. For example, we’re allowing to sort on every property of our ApiResource with a partial search filter:
// app/Models/Book.php
use ApiPlatform\Laravel\Eloquent\Filter\PartialSearchFilter;
use ApiPlatform\Laravel\Eloquent\Filter\OrderFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\QueryParameter;
#[ApiResource]
#[QueryParameter(key: 'sort[:property]', filter: OrderFilter::class)]
#[QueryParameter(key: ':property', filter: PartialSearchFilter::class)]
class Book extends Model
{
}The documentation will output a query parameter per property that applies the PartialSearchFilter and also gives the ability to sort by name and ID using: /books?name=search&order[id]=asc&order[name]=desc.
To enable partial search filtering and sorting on specific properties like name and description:
// app/Models/Book.php
use ApiPlatform\Laravel\Eloquent\Filter\PartialSearchFilter;
use ApiPlatform\Laravel\Eloquent\Filter\OrderFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\QueryParameter;
#[ApiResource]
#[QueryParameter(key: 'sort[:property]', filter: OrderFilter::class, properties: ['name', 'description'])]
#[QueryParameter(key: ':property', filter: PartialSearchFilter::class, properties: ['name', 'description'])]
class Book extends Model
{
}As shown above the following search filters are available:
ApiPlatform\Laravel\Eloquent\Filter\PartialSearchFilter queries LIKE %term%ApiPlatform\Laravel\Eloquent\Filter\EqualsFilter queries = termApiPlatform\Laravel\Eloquent\Filter\StartSearchFilter queries LIKE term%ApiPlatform\Laravel\Eloquent\Filter\EndSearchFilter queries LIKE %termThe DateFilter allows to filter dates with an operator (eq, lt, gt, lte, gte):
eq - equals (exact match)gt - greater than (strictly after)gte - greater than or equal (after or on)lt - less than (strictly before)lte - less than or equal (before or on)after - alias for gtebefore - alias for ltestrictly_after - alias for gtstrictly_before - alias for ltUsage Examples
With the DateFilter applied, you can now filter dates between 2024-01-01 and 2024-01-31 using these API calls:
Option 1: Using gte and lte operators
GET /api/your_entities?createdAt[gte]=2024-01-01&createdAt[lte]=2024-01-31Option 2: Using after and before operators
GET /api/your_entities?createdAt[after]=2024-01-01&createdAt[before]=2024-01-31Option 3: Using strictly_after and strictly_before
GET /api/your_entities?createdAt[strictly_after]=2023-12-31&createdAt[strictly_before]=2024-02-01// app/Models/Book.php
use ApiPlatform\Laravel\Eloquent\Filter\DateFilter;
#[ApiResource]
#[QueryParameter(key: 'publicationDate', filter: DateFilter::class, filterContext: ['include_nulls' => true])]
class Book extends Model
{
use HasUlids;
public function author(): BelongsTo
{
return $this->belongsTo(Author::class);
}
}Our default strategy is to exclude null values, just remove the filterContext if you want to exclude nulls.
The OrFilter allows to filter using an OR WHERE clause:
// app/Models/Book.php
use ApiPlatform\Laravel\Eloquent\Filter\DateFilter;
#[ApiResource]
#[QueryParameter(
key: 'q',
filter: new OrFilter(new EqualsFilter()),
property: 'isbn'
)]
class Book extends Model
{
use HasUlids;
public function author(): BelongsTo
{
return $this->belongsTo(Author::class);
}
}This allows to query multiple isbn values with a q query parameter: /books?q[]=9781784043735&q[]=9780369406361.
The BooleanFilter allows to filter using an WHERE clause on a boolean field with (true, false, 0, 1):
// app/Models/Book.php
use ApiPlatform\Laravel\Eloquent\Filter\BooleanFilter;
#[ApiResource]
#[QueryParameter(key: 'published', filter: BooleanFilter::class)]
class Book extends Model
{
use HasUlids;
public function author(): BelongsTo
{
return $this->belongsTo(Author::class);
}
}Examples:
/books?published=true/books?published=1/books?published=false/books?published=0Note: We strongly recommend using Vulcain instead of this filter. Vulcain is faster, allows a better hit rate, and is supported out of the box in the API Platform distribution.
The property filter adds the possibility to select the properties to serialize (sparse fieldsets).
// app/Models/Book.php
use ApiPlatform\Laravel\Eloquent\Filter\DateFilter;
use ApiPlatform\Serializer\Filter\PropertyFilter;
#[ApiResource]
#[QueryParameter(key: 'properties', filter: PropertyFilter::class)]
class Book extends Model
{
use HasUlids;
public function author(): BelongsTo
{
return $this->belongsTo(Author::class);
}
}A few filterContext options are available to configure the filter:
override_default_properties allows to override the default serialization properties (default false) Using true is dangerous, use carefully this can expose unwanted data!whitelist properties whitelist to avoid uncontrolled data exposure (default null to allow all properties)Given that the collection endpoint is /books, you can filter the serialization properties with the following query: /books?properties[]=title&properties[]=author.
To get started, API Platform includes a very handy make command to generate the basic structure of an Laravel Eloquent filter:
bin/console make:filter
Then, provide the name of your filter, for example MonthFilter, or pass it directly as an argument:
make:filter MyCustomFilter
You will get a file at app/Filter/MonthFilter.php with the following content:
<?php
// app/Filter/MonthFilter.php
<?php
declare(strict_types=1);
namespace App\Filter;
use ApiPlatform\Metadata\Parameter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
final class MonthFilter implements FilterInterface
{
/**
* @param Builder<Model> $builder
* @param array<string, mixed> $context
*/
public function apply(Builder $builder, mixed $values, Parameter $parameter, array $context = []): Builder
{
// TODO: make your awesome query using the $builder
// return $builder->
}
}Let’s create a concrete filter that allows fetching entities based on the month of a date field (e.g., createdAt).
The goal is to be able to call a URL like GET /invoices?createdAtMonth=7 to get all invoices created in July.
Here is the complete and corrected code for the filter:
<?php
// app/Filter/MonthFilter.php
<?php
declare(strict_types=1);
namespace App\Filter;
use ApiPlatform\Metadata\Parameter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
final class MonthFilter implements FilterInterface
{
/**
* @param Builder<Model> $builder
* @param array<string, mixed> $context
*/
public function apply(Builder $builder, mixed $values, Parameter $parameter, array $context = []): Builder
{
return $builder->->whereMonth($parameter->getProperty(), $values);
}
}We can now use it in our resources and model like other filters, for example, as follows:
<?php
// app/ApiResource/Invoice.php
namespace App\ApiResource;
use ApiPlatform\Metadata\QueryParameter;
use App\Filters\MonthFilter;
#[ApiResource]
#[QueryParameter(
key: 'createdAtMonth',
filter: new MonthFilter(),
property: 'createdAt'
)]
class Invoice
{
// ...
}And that’s it! ✅ Your filter is operational. A request like GET /invoices?createdAtMonth=7 will now correctly return
the invoices from July!
You can also help us improve the documentation of this page.
Made with love by
Les-Tilleuls.coop can help you design and develop your APIs and web projects, and train your teams in API Platform, Symfony, Next.js, Kubernetes and a wide range of other technologies.
Learn more