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.

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.