Generate UUID in PHP
ramsey/uuid is the PHP standard with 300M+ downloads — supports v4, v7, and v5. Laravel ships Str::uuid() built-in. PHP 8.1+ also has Symfony UID support.
Quick Reference
| Method | Version | Sortable | Use Case |
|---|---|---|---|
| Uuid::uuid4() | v4 | No | General purpose — session IDs, record IDs, API keys |
| Uuid::uuid7() | v7 | Yes | Database PKs, event logs — time-ordered |
| Uuid::uuid5() | v5 | No | Deterministic — same namespace + name = same UUID |
| Str::uuid() (Laravel) | v4 | No | Laravel helper — wraps ramsey/uuid |
Primary Implementation
<?php
use Ramsey\Uuid\Uuid;
// UUID v4 — random, CSPRNG-backed
$uuid = Uuid::uuid4();
echo $uuid->toString();
// → f47ac10b-58cc-4372-a567-0e02b2c3d479
// As a plain string
$uuidStr = (string) $uuid;
// As hex (no hyphens)
$uuidHex = $uuid->getHex()->toString();
// → f47ac10b58cc4372a5670e02b2c3d479
// As bytes (16 bytes)
$uuidBytes = $uuid->getBytes();
// Parse and validate an existing UUID string
try {
$parsed = Uuid::fromString('f47ac10b-58cc-4372-a567-0e02b2c3d479');
echo $parsed->getVersion(); // → 4
} catch (\InvalidArgumentException $e) {
echo 'Invalid UUID: ' . $e->getMessage();
}
// Generate multiple UUIDs
$ids = array_map(fn() => (string) Uuid::uuid4(), range(1, 5));
All UUID Versions
UUID v4 — Random (recommended default)
<?php use Ramsey\Uuid\Uuid; $uuid = Uuid::uuid4(); echo $uuid->toString(); // → "550e8400-e29b-41d4-a716-446655440000"
UUID v7 — Time-ordered (database PKs)
<?php use Ramsey\Uuid\Uuid; // Millisecond-precision timestamp prefix — sorts chronologically $uuid = Uuid::uuid7(); echo $uuid->toString(); // → "018e8f6a-1b2c-7d3e-9f4a-5b6c7d8e9f0a"
UUID v5 — Deterministic / Namespace-based
<?php use Ramsey\Uuid\Uuid; // SHA-1 hash of namespace + name — same inputs always produce the same UUID $uuid = Uuid::uuid5(Uuid::NAMESPACE_DNS, 'example.com'); echo $uuid->toString(); // → always "cfbff0d1-9375-5685-968c-48ce8b15ae17"
Laravel helpers
<?php use Illuminate\Support\Str; // Str::uuid() wraps ramsey/uuid — returns a UuidInterface $uuid = Str::uuid(); echo (string) $uuid; // → "f47ac10b-58cc-4372-a567-0e02b2c3d479" // Str::orderedUuid() — time-ordered, better for DB index performance $orderedUuid = Str::orderedUuid(); echo (string) $orderedUuid;
Real-World Use Cases
1. Laravel Eloquent model with UUID primary key
<?php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
class Order extends Model
{
protected $keyType = 'string';
public $incrementing = false;
protected static function boot(): void
{
parent::boot();
static::creating(function (Order $model) {
if (empty($model->id)) {
$model->id = (string) Str::uuid();
}
});
}
}
// Or use Laravel's HasUuids trait (Laravel 9+):
// use Illuminate\Database\Eloquent\Concerns\HasUuids;
2. Symfony entity with UUID PK
<?php
use Symfony\Component\Uid\Uuid;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
class Product
{
#[ORM\Id]
#[ORM\Column(type: 'uuid', unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')]
private Uuid $id;
public function __construct()
{
$this->id = Uuid::v4();
}
}
3. API idempotency key
<?php
use Ramsey\Uuid\Uuid;
function chargeCustomer(string $customerId, int $amountCents): array
{
// Generate once, store in session, reuse on retry
$idempotencyKey = (string) Uuid::uuid4();
$response = Http::withHeaders([
'Idempotency-Key' => $idempotencyKey,
])->post('https://api.stripe.com/v1/charges', [
'customer' => $customerId,
'amount' => $amountCents,
'currency' => 'usd',
]);
return $response->json();
}
Common Mistakes
Using uniqid() instead of a proper UUID
uniqid() is based on the current time in microseconds — it is not CSPRNG-backed and has a high collision probability under load. Always use Uuid::uuid4() or Str::uuid().
Not using the native UUID column type in MySQL 8+
MySQL 8.0.17+ supports UUID_TO_BIN(uuid, 1) to store UUIDs as BINARY(16) with time-bit reordering. Storing as VARCHAR(36) wastes space and causes index fragmentation.
Forgetting to cast to string when concatenating
Uuid::uuid4() returns a UuidInterface object, not a string. Use (string) $uuid or $uuid->toString() before passing to string contexts.
How It Works
ramsey/uuid uses PHP's random_bytes(16) for entropy, which maps to the OS CSPRNG (/dev/urandom on Linux, CryptGenRandom on Windows). It then sets the version and variant bits per RFC 4122.
The library returns a UuidInterface object. Cast to string with (string) or call ->toString() for the standard hyphenated format.
Output Formats
$uuid->toString()
f47ac10b-58cc-4372-a567-0e02b2c3d479
$uuid->getHex()->toString()
f47ac10b58cc4372a5670e02b2c3d479
$uuid->getBytes() — 16 bytes
binary string (16 bytes)
Best Practices
Use Uuid::uuid7() for database PKs — sequential inserts avoid B-tree fragmentation.
In Laravel 9+, use the HasUuids trait instead of manual boot hooks.
Store as BINARY(16) in MySQL or native UUID type in PostgreSQL.
Performance
PHP generates roughly 500K–1M UUIDs/second with ramsey/uuid. The bottleneck is random_bytes() — a syscall on every call.
For bulk generation, consider generating UUIDs in batches and inserting with a single multi-row INSERT rather than one INSERT per UUID.
Installation
composer require ramsey/uuid
Requires PHP 8.0+. Laravel already includes ramsey/uuid as a dependency — no extra install needed in Laravel projects.
Security
Entropy source: random_bytes() — maps to /dev/urandom on Linux/macOS and CryptGenRandom on Windows. Cryptographically secure.
Never use uniqid(), rand(), or mt_rand() for IDs. They are not CSPRNG-backed and have predictable output.