For safety reasons, you should not expose the API with an internal entity id, you can guess the next record ids or their number. Better to use UUID v7 for API.
Symfony supports UUID support via the symfony/uid component.
We can generate such an identifier with the command: Uuid::v7()
Sample result: 019d67a1-164f-740b-9dc3-aebf8ad6067c
Installation:composer require symfony/uid
For convenience, we will create a trait with the field: uid. Note that the field is of the type: Uuid, so doctrine also has ready-made solutions.
src/Entity/Traits/UidTrait.php
namespace App\Entity\Traits;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Attribute\Groups;
use Symfony\Component\Uid\Uuid;
use Symfony\Component\Validator\Constraints as Assert;
trait UidTrait
{
#[ORM\Column(type: 'uuid', unique: true)]
#[Assert\NotNull]
#[Assert\Uuid]
#[Groups(['uid:read'])]
private ?Uuid $uid = null;
public function getUid(): ?Uuid
{
return $this->uid;
}
public function setUid(Uuid $uid): static
{
$this->uid = $uid;
return $this;
}
public function generateUid(): void
{
$this->uid = Uuid::v7();
}
}When creating an entity, you must also generate a uid. We can do this in Factory or in the constructor. I prefer the first variant.
src/Entity/Book.php
use UidTrait;
public function __construct()
{
$this->generateUid();
}In nelmio_api_doc.yml we can describe the field as follows:
config/packages/nelmio_api_doc.yaml
schemas:
BookItem:
type: object
properties:
uid:
type: string
format: uuid
description: "Publiczny identyfikator zasobu (UUID v7)"
example: "019d67a1-16c1-7da8-969a-4cc234a268bf"An interesting thing is the way it is stored in the database. It is a binary(16) field, takes up less space than a string and is much faster when searching.
Query examples
With pure SQL you need to convert uuid to binary:
SELECT * FROM book WHERE uid = UUID_TO_BIN('019d67a1-16c1-7da8-969a-4cc234a268bf');
or vice versa:
SELECT BIN_TO_UUID(uid) AS uuid FROM book;
Doctrine handles uuid fields automatically:
$repository->findOneBy(['uid' => $uuidString]);In queries it returns uid as an object:
^ Symfony\Component\Uid\UuidV7^ {#3052
#uid: "019d8ff9-d693-7ab7-8883-33f55c46621d"
toBase58: "1Ca58yqL2XeVRufqYUKVQQ"
toBase32: "01KP7ZKNMKFAVRH0SKYNE4CRGX"
time: "2026-04-15 07:10:08.531685 UTC"
}For QueryBuilder, if $uid is a string:
$result = $this->createQueryBuilder('b')
->andWhere('b.uid = :uid')
->setParameter('uid', $uid, 'uuid')
->getQuery()
->getOneOrNullResult()
;For Query Builder, if $uid is a UuidV7 object:
$result = $this->createQueryBuilder('b')
->andWhere('b.uid = :uid')
->setParameter('uid', $uid->toBinary())
->getQuery()
->getOneOrNullResult()
;

Leave a Reply