Every item operation has an identifier in its URL. Although this identifier is usually a number, it can also be an UUID
, a date, or the type of your choice.
To help with your development experience, we introduced an identifier normalization process.
In the following chapter, we’re assuming that
App\Uuid
is a project-owned class that manages a time-based UUID.
Let’s say you have the following class, which is identified by a UUID
type. In this example, UUID
is not a simple string but an object with many attributes.
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use App\Uuid;
#[ApiResource]
final class Person
{
/**
* @var Uuid
*/
#[ApiProperty(identifier: true)]
public $code;
// ...
}
# api/config/api_platform/resources/Person.yaml
App\Entity\Person:
properties:
code:
identifier: true
<resources xmlns="https://api-platform.com/schema/metadata">
<resource class="App\EntityPerson">
<property name="code" identifier="true"/>
</resource>
</resources>
Once registered as an ApiResource
, having an existing person, it will be accessible through the following URL: /people/110e8400-e29b-11d4-a716-446655440000
.
Note that the property identifying our resource is named code
.
Let’s create a DataProvider
for the Person
entity:
<?php
namespace App\DataProvider;
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
use App\Entity\Person;
use App\Uuid;
final class PersonDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
{
/**
* {@inheritdoc}
*/
public function getItem(string $resourceClass, $identifiers, string $operationName = null, array $context = [])
{
// Our identifier is:
// $identifiers['code']
// although it's a string, it's not an instance of Uuid and we wanted to retrieve the timestamp of our time-based uuid:
// $identifiers['code']->getTimestamp()
}
/**
* {@inheritdoc}
*/
public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
{
return $resourceClass === Person::class;
}
}
To cover this use case, we need to denormalize
the identifier to an instance of our App\Uuid
class. This case is covered by an identifier denormalizer:
<?php
namespace App\Identifier;
use ApiPlatform\Core\Exception\InvalidIdentifierException;
use App\Uuid;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
final class UuidNormalizer implements DenormalizerInterface
{
/**
* {@inheritdoc}
*/
public function denormalize($data, $class, $format = null, array $context = [])
{
try {
return Uuid::fromString($data);
} catch (InvalidUuidStringException $e) {
throw new InvalidIdentifierException($e->getMessage());
}
}
/**
* {@inheritdoc}
*/
public function supportsDenormalization($data, $type, $format = null)
{
return is_a($type, Uuid::class, true);
}
}
Tag this service as an api_platform.identifier.denormalizer
:
services:
App\Identifier\UuidNormalizer:
tags:
- { name: api_platform.identifier.denormalizer }
<service id="App\Identifier\UuidNormalizer" class="App\Identifier\UuidNormalizer" public="false">
<tag name="api_platform.identifier.denormalizer" />
</service>
Your PersonDataProvider
will now work as expected!
If your resource is also a Doctrine entity and you want to use another identifier other than the Doctrine one, you have to unmark it:
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use App\Uuid;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
#[ApiResource]
final class Person
{
#[ORM\Id, ORM\Column, ORM\GeneratedValue]
#[ApiProperty(identifier: false)]
private ?int $id = null;
/**
* @var Uuid
*/
#[ORM\Column(type: 'uuid', unique: true)]
#[ApiProperty(identifier: true)]
public $code;
// ...
}
API Platform supports the following identifier types:
scalar
(string, integer)\DateTime
(uses the symfony DateTimeNormalizer
internally, see DateTimeIdentifierNormalizer)\Ramsey\Uuid\Uuid
(see UuidNormalizer)\Symfony\Component\Uid\Ulid
(see UlidNormalizer)\Symfony\Component\Uid\Uuid
(see UuidNormalizer)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