# Identifiers
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.
## Custom Identifier Normalizer
> [!WARNING] This feature is not yet available with Laravel, if you need it please open a Feature
> Request issue! 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
```
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 `Provider` for the `Person` resource:
```php
*/
final class PersonProvider implements ProviderInterface
{
public function provide(Operation $operation, array $uriVariables = [], array $context = []): Person
{
// Our identifier is:
// $uriVariables['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:
// $uriVariable['code']->getTimestamp()
}
}
```
To cover this use case, we need to `transform` the identifier to an instance of our `App\Uuid`
class. This case is covered by an URI variable transformer:
```php
getMessage());
}
}
/**
* Checks whether the given uri variable is supported for transformation by this transformer.
*
* @param mixed $value The uri variable value to transform
* @param array $types The types to which the data should be transformed
* @param array $context Options available to the transformer
*/
public function supportsTransformation($value, array $types, array $context = []): bool
{
foreach ($types as $type) {
if (is_a($type, Uuid::class, true)) {
return true;
}
}
return false;
}
}
```
Tag this service as an `api_platform.uri_variables.transformer` using one of the configurations
below:
### Tag the Service using Symfony
```yaml
# api/config/services.yaml
# The YAML syntax is only supported for Symfony
services:
App\Identifier\UuidUriVariableTransformer:
tags:
- { name: api_platform.uri_variables.transformer }
```
```xml
```
Your `PersonProvider` will now work as expected!
## Decorating the IdentifiersExtractor
The `IdentifiersExtractor` is responsible for extracting identifiers from a resource. By default,
when `\DateTime` objects are used as identifiers, their serialization to `IRI` format is handled by
the `DateTimeUriVariableTransformer`, which internally uses Symfony's `DateTimeNormalizer`. If you
need a custom format, you can decorate the `IdentifiersExtractor`.
Let's say you want to format all `\DateTime` identifiers to `Y-m-d`.
First, create a custom `IdentifiersExtractor` that decorates the original:
```php
decorated->getIdentifiersFromItem($item, $options);
foreach ($identifiers as $key => $value) {
if ($value instanceof DateTimeInterface) {
$identifiers[$key] = $value->format('Y-m-d');
}
}
return $identifiers;
}
}
```
Then, configure the service decoration in your `services.yaml`:
```yaml
# api/config/services.yaml
services:
App\Identifier\DateTimeIdentifiersExtractor:
decorates: "api_platform.identifiers.identifiers_extractor"
arguments: ["@.inner"]
public: false
```
```xml
```
Now, all `\DateTime` identifiers will be formatted as `Y-m-d` in your resource IRIs.
## Changing Identifier in a Doctrine Entity
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