API Platform 3.1

API Platform 3.1 is out!

webby api platform 3.1

The API Platform core team released the next minor version, API Platform 3.1. This version is backed by Les-Tilleuls.coop and is the work of many contributors, thanks to them!

We had really amazing feedbacks on API Platform 3, we have now released API Platform 3.0.11 and API Platform 2.7.7. Note that if you haven’t upgraded yet to 3.0, you really need to as the 2.7 version will now only get security updates. If you’re not comfortable or think that it’s too hard to upgrade contact us, we can help!

State options

One of my preferred feature is the ability to configure stateOptions on an Operation. It will help in a separation between the PHP class we use to represent the API Resource and the PHP class used for persistence in a Doctrine environment. This feature was based on discussions with C0il when he worked on replacing endpoints with API Platform 3 and Pierstoval at a PHP conference. In API Platform 3.1 you have access to a stateOptions property allowing you to use another class as Doctrine entity:

use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Doctrine\Orm\State\Options;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\SeparatedEntity;

#[ApiResource(shortName: 'SeparatedEntity', stateOptions: new Options(entityClass: SeparatedEntity::class))]
class ResourceWithSeparatedEntity
{
	public string $id;
	#[ApiFilter(OrderFilter::class)]
	public string $value;
}

The same mechanism was added to Elasticsearch to customize the index used see ApiPlatform\Elasticsearch\State\Options.

PUT is now spec-compliant

Our current implementation of the PUT HTTP method is not standard-compliant: according to the spec, a PUT must create or replace the resource at the requested URL. From API Platform 3.1, you can enable the creation of a resource via PUT using allowCreate: true.

Prepare the backward compatibility change in 4! In API Platform 4, PUT will replace the data. To make sure that your code is working this way, we recommend to set:

defaults:
    extra_properties:
        standard_put: true

It will ensure that you’ll be ready for the next major version. In API Platform 3.1 the default value is false so that your expected behavior doesn’t change.

Find all the implementation details on GitHub and thanks to @dunglas for making this happen!

Enums support

Finally after quite some time (this issue was opened in 2018!), we have support for Enums in OpenAPI, REST and GraphQL. Both Doctrine ORM and ODM have support for enums through enumType which is supported by API Platform 3.0. Alan added their support over OpenAPI and GraphQL.

HTTP cache purger revisited

We refactored our Surrogate key Purger to make it provider agnostic and we added a Purger for Souin, a Go HTTP cache provider that works as a Caddy module!

OpenAPI customization enhancement

For small OpenAPI changes, it was often necessary to decorate the OpenApiFactory. In API Platform 3.1 you can use the openapi option with a ApiPlatform\OpenApi\Model\Operation object allowing you to use the exact same Value Object used to generate the OpenApi documentation:

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Post;
use ApiPlatform\OpenApi\Model;
use App\Controller\RandomRabbit;

#[ApiResource]
#[Post(
	name: 'create_rabbit',
	uriTemplate: '/rabbit/create',
	controller: RandomRabbit::class,
	openapi: new Model\Operation(
    	summary: 'Create a rabbit picture',
    	description: '# Pop a great rabbit picture by color!\n\n![A great rabbit](https://rabbit.org/graphics/fun/netbunnies/jellybean1-brennan1.jpg)',
    	requestBody: new Model\RequestBody(
        	content: new \ArrayObject([
            	'application/json' => [
                	'schema' => [
                    	'type' => 'object',
                    	'properties' => [
                        	'name' => ['type' => 'string'],
                        	'description' => ['type' => 'string']
                    	]
                	],
                	'example' => [
                    	'name' => 'Mr. Rabbit',
                    	'description' => 'Pink Rabbit'
                	]
            	]
        	])
    	)
	)
)]
class Rabbit
{
	// ...
}

This openapi option also takes the false value to remove your operation from the documentation.

Collect denormalization errors

As of Symfony 5.4, thanks to Lyrixx we can collect multiple denormalization type errors. Natacha added this as an opt-in feature to API Platform 3.1:

use ApiPlatform\Metadata\ApiResource;
#[ApiResource(
	collectDenormalizationErrors: true
)]
class Book
{
}

Through this blog post we showcase only half of the new stuff, don’t forget to check the CHANGELOG for the details related to this release!