PHP’s most widely used framework, Laravel, has supported UUID primary keys since Laravel 9 through the HasUuids trait. UUID v7 support requires a small customization, but the ecosystem is rapidly catching up.
Generating UUIDs in PHP
ramsey/uuid is the definitive UUID library for PHP:
composer require ramsey/uuid
use Ramsey\Uuid\Uuid;
$v4 = Uuid::uuid4()->toString(); // "550e8400-e29b-41d4-a716-446655440000"
$v7 = Uuid::uuid7()->toString(); // "018fbe3a-4c5d-7000-8abc-0123456789ab"
ramsey/uuid implements RFC 9562 including monotonic counter support for UUID v7. It is the most downloaded PHP package after the Laravel framework itself.
Laravel also includes Str::uuid() (wraps ramsey/uuid v4) and Str::orderedUuid() (generates a time-ordered UUID compatible with v7 semantics) without a direct dependency.
Laravel Eloquent UUID Primary Keys
UUID v4 — the default HasUuids trait:
use Illuminate\Database\Eloquent\Concerns\HasUuids;
class Order extends Model
{
use HasUuids;
// newUniqueId() defaults to Str::uuid() → UUID v4
}
UUID v7 — override newUniqueId():
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Ramsey\Uuid\Uuid;
class Order extends Model
{
use HasUuids;
public function newUniqueId(): string
{
return Uuid::uuid7()->toString();
}
}
The migration stays unchanged — $table->uuid('id')->primary() creates the correct column regardless of UUID version.
MySQL Storage — Use char(36) or binary(16)
Laravel’s $table->uuid() creates a char(36) column in MySQL. For best performance at scale, store as binary(16) instead:
// Migration
$table->binary('id', 16)->primary();
Then cast in the model using a custom cast:
protected $casts = [
'id' => UuidBinarycast::class,
];
The ramsey/uuid library includes a Laravel bridge with ready-made Eloquent casts for both char(36) and binary(16) storage.
PostgreSQL — Native uuid Type
On PostgreSQL backends, Laravel’s $table->uuid() maps to PostgreSQL’s native uuid column type, which stores 16 bytes efficiently. UUID v7 inserts land in ascending index order, avoiding the B-tree fragmentation that UUID v4 causes at scale.
Related Resources
- ramsey/uuid documentation — PHP UUID library with full RFC 9562 support
- Laravel Eloquent UUID and ULID keys documentation
- PHP uuid extension reference
- RFC 9562 — UUID v7 standard
Frequently asked questions
How do I generate UUID v7 in PHP and Laravel?
Use the ramsey/uuid Composer package: Uuid::uuid7()->toString(). In Laravel, override newUniqueId() in a model that uses the HasUuids trait to return a UUID v7 string. The database char(36) or PostgreSQL uuid column type stores it without schema changes.
Do UUIDs hurt database index performance?
UUID v4 does — its randomness causes every insert to land at a different leaf page, leading to page splits and poor cache locality. UUID v7 embeds a millisecond timestamp so consecutive inserts cluster together, behaving like an auto-increment integer for B-tree purposes.
Does PostgreSQL 18 support UUID v7 natively?
Yes. PostgreSQL 18 ships a built-in uuidv7() function that generates RFC 9562-compliant UUID v7 values directly in SQL — no extensions or application-level generation required. The values store in the existing uuid column type unchanged.
How do I generate a UUID in PHP?
PHP 7.4+ does not include a native UUID function. The two common approaches are the ramsey/uuid Composer package (Uuid::uuid4() / Uuid::uuid7()) or Laravel's built-in Str::uuid() (v4) and Str::orderedUuid() (v7-style time-ordered). PHP 8.4 is expected to add a native uuid_create() function.
Does Laravel support UUID v7 primary keys natively?
Laravel 10+ ships $table->uuid('id') in migrations and the HasUuids trait, which calls Str::uuid() (UUID v4). For UUID v7, override newUniqueId() in your model to call Str::orderedUuid() or \Ramsey\Uuid\Uuid::uuid7(). See the Laravel Eloquent UUID documentation for the full pattern.