The Uid component provides utilities to work with unique identifiers such as UUIDs and ULIDs. In Symfony 7.4, we've added several new features related to UUIDs.
Default to UUID v7
UUID v7 is a recent addition to the UUID specification that generates time-ordered UUIDs based on a high-resolution Unix Epoch timestamp source. It's an improved version over UUID v1 and UUID v6, and it's now the recommended option instead of those older versions.
Starting in Symfony 7.4, UUID v7 is used by default when creating UUID values via a factory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
namespace App\Service;
use Symfony\Component\Uid\Factory\UuidFactory;
class FooService
{
public function __construct(
private UuidFactory $uuidFactory,
) {
}
public function generate(): void
{
// both UUIDs will use UUID v7 by default
$uuid = $this->uuidFactory->create();
$timestampBasedUuid = $this->uuidFactory->timeBased()->create();
// ...
}
}
If you need to generate a different version, you can configure the default values used by the factory:
1 2 3 4 5 6
# config/packages/uid.yaml
framework:
uid:
default_uuid_version: 6
time_based_uuid_version: 1
# ...
Add Microsecond Precision to UUID v7
The time component of UUID v7 values provides millisecond precision. However, the UUID spec mentions that "it is possible to use additional clock precision [...] to provide values that are time ordered with sub-millisecond precision".
In Symfony 7.4, we're updating UUID v7 generation to include microsecond precision. You don't have to do anything to benefit from this new feature. Just update to Symfony 7.4 and any new UUIDs you create will include this microsecond precision. This comes with a nice performance improvement that reduces the generation time by 10%.
UUID Test Factory
Many UUID versions include random or time-dependent parts, which makes them
hard to use in tests. In Symfony 7.4, we're introducing a MockUuidFactory
to make your UUIDs predictable and reproducible in tests.
First, your services using UUIDs must rely on the UuidFactory
to create them:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
use Symfony\Component\Uid\Factory\UuidFactory;
use Symfony\Component\Uid\Uuid;
class UserService
{
public function __construct(
private UuidFactory $uuidFactory
){
}
public function createUserId(): string
{
return $this->uuidFactory->create()->toRfc4122();
}
// ...
}
Then, when testing those services, use a MockUuidFactory
to define the
list of UUIDs that will be returned for each call to create a new UUID value:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
use PHPUnit\Framework\TestCase;
use Symfony\Component\Uid\Factory\MockUuidFactory;
use Symfony\Component\Uid\UuidV4;
class UserServiceTest extends TestCase
{
public function testCreateUserId()
{
$factory = new MockUuidFactory([
UuidV4::fromString('11111111-1111-4111-8111-111111111111'),
UuidV4::fromString('22222222-2222-4222-8222-222222222222'),
]);
$service = new UserService($factory);
$this->assertSame('11111111-1111-4111-8111-111111111111', $service->createUserId());
$this->assertSame('22222222-2222-4222-8222-222222222222', $service->createUserId());
}
}
In addition to the create()
method, it also supports randomBased()
,
timeBased()
, and nameBased()
methods. You can also mix different UUID
versions in the list of returned values.