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
- Using
uniqid()instead of a real UUID.uniqid()is not a UUID — it is a microtime-based identifier with no collision guarantees and no RFC 9562 format. UseUuid::uuid4()orStr::uuid(). - Storing as
VARCHAR(36). Use Laravel’suuid()migration helper which creates the appropriate native type. For MySQL, considerBINARY(16)with UUID conversion helpers. - Comparing strings with mixed case. UUID strings are case-insensitive but PHP string comparison is case-sensitive. Normalise to lowercase before comparing:
strtolower($uuid). - Using
Str::orderedUuid()for cross-system compatibility. Laravel’s ordered UUID format is not standard UUID v7. UseUuid::uuid7()if the ID must be read by other services or databases.
Related guides
- UUID v4 vs UUID v7 — which version to use and why
- UUID in databases — MySQL BINARY(16) vs VARCHAR(36)
- UUID in PHP and Laravel — HasUuids, Eloquent, and MySQL patterns
- UUID v7 ORM support — state of all ORMs in 2026
External references
- github.com/ramsey/uuid: ramsey/uuid — the standard PHP UUID library, source code, changelog, and issues
- Packagist — ramsey/uuid: package stats, install counts, and version history for the ramsey/uuid Composer package
- Laravel Docs — UUID and ULID keys: official Laravel documentation for HasUuids trait, newUniqueId(), and Eloquent UUID primary keys
- GeeksforGeeks — PHP ramsey/uuid: practical guide to installing and using ramsey/uuid for v4 and v7 in PHP projects
- dev.to — Using UUID in Laravel: community guide on HasUuids, Str::uuid(), and Laravel migration patterns
- Medium — UUID v7 in Laravel 11: migration guide for switching from Str::orderedUuid() to ramsey/uuid v7 in Eloquent models
- Shopify Developer Docs — Idempotent requests: real-world example of UUID-based idempotency keys in a major PHP-based e-commerce platform
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.