BackedEnumFilter: a new Doctrine filter for API Platform
Through this short article, I’d like to share my latest contribution to an open source project: API Platform.
API Platform is a well-known PHP framework that enables you to quickly build robust web APIs. With just a few configurations, you can expose REST and GraphQL APIs in minutes. However, it is also highly configurable and extensible to fit your specific logic.
As you probably know, PHP 8.1 introduced support for Enumerations, a feature which already exists in many other languages. In a nutshell, Enums allow us to define a type that is restricted to a custom set of values. PHP provides 2 kinds of Enums:
<?php
// "Pure Enum"
enum ArticleStatus
{
case Archived;
case Draft;
case Published;
}
// "Backed Enum"
enum UserStatus: string
{
case Active = 'active';
case Blocked = 'blocked';
}
Each case of a “Pure Enum” is simply a singleton object with no related data whereas a case of a “Backed Enum” has a scalar representation (a string in this snippet), and can therefore be stored in a database.
Please note that both Pure and Backed Enums can also declare constants and methods, implement interfaces and use traits. However, this is beyond the scope of this article. If you want to explore further, you can deep dive into all these features in the official documentation and/or related articles.
Out-of-the-box API Platform provides a lot of features like pagination, validation, security…and filters. Filters allow to …🥁… filter 👻 and sort data from Doctrine ODM, Doctrine ORM and Elasticsearch. You can use built-in filters (boolean, date, order, …) and create your own, but Backed Enums are not supported yet. So, I decided to contribute to the project by adding a new Doctrine ORM filter to handle them. Let’s dive in!
Before starting, I opened an issue to ensure this feature would be useful to others besides myself, and it was quickly approved by Antoine Bluchet, one project maintainer.
Following the guidelines for contributing, I was able to implement it with documentation and tests and create a pull request. The code was rapidly reviewed, and after a few iterations, it was merged 🥳. In a sum up, the new filter is called “BackedEnumFilter” and it allows you to filter entities by their Backed Enum properties. Here is an example of how to use it with PHP attributes (yaml and xml are also supported):
<?php
namespace App\Entity;
use ApiPlatform\Doctrine\Orm\Filter\BackedEnumFilter;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiResource;
use App\Enum\UserStatus;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
#[ApiResource]
#[ApiFilter(BackedEnumFilter::class, properties: ['status', 'group.status'])]
class User
{
#[ORM\Column(enumType: UserStatus::class, options: ['default' => UserStatus::Active])]
private UserStatus $status = UserStatus::Active;
#[ORM\ManyToOne]
private Group $group;
}
As a result, you’ll be able to filter users by their status (active or blocked). Moreover, the filter also supports nested properties: for example, if a user is related to a group that also has a status property, you can apply the filter on it as well!
As Antoine mentioned in his post, you can currently test this new feature by installing v3.4.0-alpha.2 (or last alpha), but it is expected to be part of API Platform 3.4 and 4.0 🎉. I hope it will be useful, feedback is welcome!