ramsey/uuid — the standard PHP UUID library

PHP has no built-in UUID generator. ramsey/uuid is the standard — install it via Packagist:

composer require ramsey/uuid
use Ramsey\Uuid\Uuid;

// UUID v4 — random, cryptographically secure
$id = Uuid::uuid4();
echo $id->toString(); // "550e8400-e29b-41d4-a716-446655440000"
echo (string)$id;     // same — __toString() calls toString()

// UUID v7 — time-sortable
$id7 = Uuid::uuid7();
echo $id7->toString(); // "018f3c4e-7a21-7b3c-9d4e-5f6a7b8c9d0e"

// UUID v5 — deterministic from namespace + name
$ns = Uuid::NAMESPACE_URL;
$id5 = Uuid::uuid5($ns, "https://example.com/products/123");
echo $id5->toString(); // always the same value

UUID v4 and v7 in plain PHP

use Ramsey\Uuid\Uuid;

// UUID v4
$id_v4 = Uuid::uuid4()->toString();

// UUID v7 — time-ordered, better for database primary keys
$id_v7 = Uuid::uuid7()->toString();

// Get components
$uuid = Uuid::uuid7();
echo $uuid->getVersion(); // 7
echo $uuid->getDateTime()->format('Y-m-d H:i:s'); // creation time (v7 only)

Laravel — HasUuids trait

Laravel 9+ includes the HasUuids trait in Eloquent for zero-config UUID primary keys. The official Laravel documentation covers this trait in full:

use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    use HasUuids;

    // HasUuids sets $incrementing = false and $keyType = 'string' automatically
    // It generates a UUID v4 for 'id' on every new model instance
}
// Create a record — UUID generated automatically
$order = Order::create(['status' => 'pending', 'total' => 99.99]);
echo $order->id; // "550e8400-e29b-41d4-a716-446655440000"

// Find by UUID
$order = Order::find('550e8400-e29b-41d4-a716-446655440000');

For UUID v7 as the primary key (better for database indexes), override newUniqueId():

use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Model;
use Ramsey\Uuid\Uuid;

class Order extends Model
{
    use HasUuids;

    public function newUniqueId(): string
    {
        return Uuid::uuid7()->toString(); // time-sortable UUID v7
    }
}

Laravel Str helpers

Laravel provides UUID helpers on the Str facade:

use Illuminate\Support\Str;

// UUID v4 — random
$id = Str::uuid()->toString(); // "550e8400-e29b-41d4-a716-446655440000"

// Ordered UUID — time-based sequential (Laravel's own format, not standard UUID v7)
$orderedId = Str::orderedUuid()->toString();

Str::orderedUuid() uses a Laravel-specific time-based format that sorts correctly as a string, but it is not the same as RFC 9562 UUID v7. For standard UUID v7 compatibility across languages and databases, use Uuid::uuid7() directly.

Parsing and validating UUIDs

use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\Exception\InvalidUuidStringException;

// Parse — throws InvalidUuidStringException on invalid input
$uuid = Uuid::fromString("550e8400-e29b-41d4-a716-446655440000");
echo $uuid->getVersion(); // 4

// Safe parse
function parseUuid(string $s): ?string {
    try {
        return Uuid::fromString($s)->toString();
    } catch (InvalidUuidStringException $e) {
        return null;
    }
}

// Validate with regex (no package required)
function isValidUuid(string $s): bool {
    return (bool) preg_match(
        '/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i',
        $s
    );
}

Database migration — Laravel

Always use uuid() column type in migrations, never string():

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('orders', function (Blueprint $table) {
            $table->uuid('id')->primary(); // 36-char string in MySQL, native uuid in PG
            $table->string('status');
            $table->decimal('total', 10, 2);
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('orders');
    }
};

For MySQL, consider BINARY(16) instead of VARCHAR(36) for better index performance:

// MySQL — BINARY(16) is 2.25x more space-efficient than uuid() / VARCHAR(36)
$table->binary('id', 16)->primary();
// Convert between string and binary in application code
// Store: hex2bin(str_replace('-', '', $uuid))
// Read: sprintf('%s-%s-%s-%s-%s',
//     substr(bin2hex($binary), 0, 8), substr(bin2hex($binary), 8, 4),
//     substr(bin2hex($binary), 12, 4), substr(bin2hex($binary), 16, 4),
//     substr(bin2hex($binary), 20))

See UUID in databases for the full storage comparison.

WordPress — wp_generate_uuid4()

WordPress 4.7+ includes a built-in UUID v4 generator — no plugin required:

// Built into WordPress core — no import needed
$id = wp_generate_uuid4();
echo $id; // "550e8400-e29b-41d4-a716-446655440000"

// Validate a UUID in WordPress
$is_valid = wp_is_uuid($id); // true
$is_valid_v4 = wp_is_uuid($id, 4); // true — validates version 4 specifically

wp_generate_uuid4() uses wp_rand() internally, which falls back to openssl_random_pseudo_bytes() or random_bytes(). For security-sensitive UUIDs, use ramsey/uuid instead, which always uses random_bytes(). Real-world PHP platforms like Shopify use UUID-based idempotency keys in their public APIs, illustrating the production importance of correct UUID generation in PHP applications.

Common mistakes

External references

Frequently asked questions

How do I generate a UUID in PHP?

Install the ramsey/uuid package (composer require ramsey/uuid) and call Uuid::uuid4()->toString() for UUID v4 or Uuid::uuid7()->toString() for UUID v7. Laravel provides Str::uuid() (v4) and the HasUuids trait for zero-config Eloquent primary keys.

How do I generate a UUID in WordPress?

WordPress 4.7+ includes wp_generate_uuid4() in core — no plugin needed. It generates a UUID v4 string. For validation, use wp_is_uuid($id) or wp_is_uuid($id, 4) to validate version specifically. For UUID v7 in WordPress plugins, use the ramsey/uuid Composer package.

What column type should I use to store a UUID in a database?

Use the native type where one exists — uuid in PostgreSQL, uniqueidentifier in SQL Server. In MySQL use BINARY(16) and store raw bytes. Avoid VARCHAR(36): it costs 36 bytes per row versus 16 for binary and makes every comparison a string operation.

How do I generate a UUID in PHP?

Install the ramsey/uuid package (composer require ramsey/uuid) and call Uuid::uuid4()->toString() for a random UUID v4, or Uuid::uuid7()->toString() for a time-sortable UUID v7. Laravel provides Str::uuid() for v4 and Str::orderedUuid() for sequential UUIDs.

How do I use UUID as a primary key in Laravel?

Add the HasUuids trait to your Eloquent model — it automatically generates a UUID v4 primary key for each new row. For UUID v7, override the newUniqueId() method to return Str::orderedUuid() or a ramsey/uuid v7 value.

What is the best PHP UUID package?

ramsey/uuid is the standard — it is widely used, well-maintained, and supports v1, v3, v4, v5, v6, and v7. Laravel uses it internally for Str::uuid(). Install with composer require ramsey/uuid.

Does PHP have a built-in UUID function?

No. PHP has no native UUID function. Use the ramsey/uuid package or Laravel's Str::uuid() helper. PHP 8.x does not include a uuid_generate() function in its standard library.

How do I generate a UUID in PHP without a library?

You can generate a UUID v4 using random_bytes() and sprintf(), but this is error-prone. The recommended approach is to use ramsey/uuid or Laravel's Str::uuid() which handles edge cases and RFC 9562 compliance correctly.

What is wp_generate_uuid4 in WordPress?

wp_generate_uuid4() is a WordPress core function that generates a UUID v4 string. It is built into WordPress 4.7+ and requires no additional packages. Use it instead of a custom implementation when building WordPress plugins or themes.