symfony/uid
Symfony UID provides an object-oriented API to generate and represent unique identifiers. Supports ULIDs and UUIDs (v1 and v3–v8) with implementations that work on both 32-bit and 64-bit CPUs.
Installation:
composer require symfony/uid
For Laravel, no additional configuration is needed beyond requiring the package.
First Use Case: Generate a UUIDv7 (time-sortable) in a Laravel controller:
use Symfony\Uid\Uuid;
use Symfony\Uid\UuidV7;
// Generate a UUIDv7 (default in Symfony 8+)
$uid = Uuid::v7();
$uidString = $uid->toRfc9562(); // e.g., "v7:018a0b1c2d3e4f56..."
// Or explicitly:
$uid = UuidV7::generate();
Where to Look First:
symfony/uid GitHub (for edge cases)Uuid (factory) and Ulid classes for daily use.Binary Storage (Recommended for Performance):
use Illuminate\Database\Eloquent\Model;
use Symfony\Uid\UuidV7;
class Post extends Model
{
protected $keyType = 'string';
public $incrementing = false;
protected $casts = [
'id' => 'uuid',
];
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->id = UuidV7::generate()->toBinary();
});
}
}
Schema::create('posts', function (Blueprint $table) {
$table->binary('id')->primary(); // Store as binary(16)
$table->timestamps();
});
String Storage (Legacy Systems):
$table->string('id', 36)->primary(); // CHAR(36) for UUIDv4/v7
return response()->json([
'id' => $post->id->toRfc9562(), // "v7:018a0b1c2d3e4f56..."
'shareable_id' => $post->id->toBase58(), // "2J...X" (URL-safe)
]);
use Symfony\Component\Uid\Uid;
$isValid = Uid::isValid($request->input('id')); // true/false
MockUuidFactory for reproducible tests:
use Symfony\Uid\Test\MockUuidFactory;
use Symfony\Uid\Uuid;
beforeEach(function () {
Uuid::setFactory(new MockUuidFactory('2023-01-01T00:00:00Z'));
});
test('generates same UUID for timestamp', function () {
$uid1 = Uuid::v7();
$uid2 = Uuid::v7();
expect($uid1->toString())->toBe($uid2->toString());
});
use Symfony\Uid\Ulid;
$ulid = Ulid::generate();
$ulidString = $ulid->toString(); // "01H5Z2X3Y4...ABCD"
UuidFactory interface for dependency injection:
$this->app->bind(\Symfony\Component\Uid\UuidFactory::class, function () {
return \Symfony\Component\Uid\Uuid::getFactory();
});
AbstractUid for domain-specific logic:
use Symfony\Component\Uid\AbstractUid;
class CustomUid extends AbstractUid
{
public static function generate(): static
{
return new self(self::generateBytes());
}
public function toDomainString(): string
{
return 'CUST-' . $this->toRfc9562();
}
}
CREATE INDEX idx_posts_id ON posts (id); -- Works on BINARY(16)
CHAR(36) for UUIDs—it’s slower to index and compare.toRfc9562() for new APIs (e.g., v7:...) and toRfc4122() for legacy compatibility:
// API v1 (legacy)
$uid->toRfc4122(); // "123e4567-e89b-12d3-a456-426614174000"
// API v2 (modern)
$uid->toRfc9562(); // "v7:018a0b1c2d3e4f56..."
Binary Storage (BINARY(16)):
toRfc9562() for readability).\Log::info('UID:', ['id' => $uid->toRfc9562()]);
String Storage (CHAR(36)):
toBinary() in queries and convert to string only for APIs.UuidV7 (time + randomness) or UuidV4 (random) instead.01H5... < 01H6...).MockUuidFactory is set globally:
// In a test trait or service provider
Uuid::setFactory(new MockUuidFactory('2023-01-01T00:00:00Z'));
composer.json).symfony/uid:^7.4 for PHP 8.1 or ^8.0 for PHP 8.4+.if (!Uid::isValid($uidString)) {
throw new \InvalidArgumentException("Invalid UID: {$uidString}");
}
$uuid = Uid::fromString($id);
\Log::debug('UUID version:', ['version' => $uuid->getVersion()]);
UUID type or BYTEA.BINARY(16).CHAR(36) but accept performance tradeoffs.UuidV7 generates different timestamps in CI vs. local:
//
How can I help you explore Laravel packages today?