Skip to content
100% in your browser. Nothing you paste is uploaded — all processing runs locally. Read more →

Generating UUIDs in PHP

On this page
  1. Quick start with ramsey/uuid
  2. Parsing
  3. Generate a UUID in PHP without a library
    1. Don’t use uniqid() for UUIDs
  4. Symfony alternative: symfony/uid
  5. Laravel
  6. Symfony / Doctrine ORM
  7. Database storage
  8. JSON serialization
  9. Validation in HTTP routes
  10. Performance
  11. Common pitfalls
  12. FAQ
    1. Does PHP have a built-in UUID function?
    2. Which PHP UUID library should I use?
    3. How do I generate a UUID in Laravel?
    4. Should I use UUID v4 or v7 in PHP?
    5. How do I store a ramsey/uuid in a Doctrine entity?
  13. Cheat sheet
  14. Try the tools

To generate a UUID in PHP, install ramsey/uuid with Composer and call Uuid::uuid4() for a random ID or Uuid::uuid7() for a time-ordered one (v7 needs ramsey/uuid 4.5 or later). PHP’s core has no built-in UUID function, so ramsey/uuid or symfony/uid is the usual route. Laravel HasUuids, Symfony Doctrine and MySQL storage examples follow.

Quick start with ramsey/uuid

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

$id = Uuid::uuid4();                                    // v4 random
$v7 = Uuid::uuid7();                                    // time-ordered (4.5+)
$v5 = Uuid::uuid5(Uuid::NAMESPACE_URL, 'https://example.com/users/42');

echo $id->toString();                                   // canonical
echo (string) $id;                                      // same — implements Stringable
echo $id->getHex();                                     // no hyphens
echo bin2hex($id->getBytes());                          // 32-char hex from 16 bytes

UuidInterface is immutable, comparable, and serializable. Cast to string anywhere a string is expected.

Parsing

use Ramsey\Uuid\Uuid;

$id = Uuid::fromString('0e6f1b8c-2c33-4f1f-9c0b-2a3d4e5f6a7b');
$id = Uuid::fromBytes($binary);
$valid = Uuid::isValid($input);

fromString throws InvalidUuidStringException on invalid input. Use Uuid::isValid() first if you’re not sure.

Generate a UUID in PHP without a library

If you can’t add a Composer dependency, PHP 7 and later can build a valid v4 UUID from random_bytes():

function uuidv4(): string
{
    $b = random_bytes(16);
    $b[6] = chr((ord($b[6]) & 0x0f) | 0x40); // version 4
    $b[8] = chr((ord($b[8]) & 0x3f) | 0x80); // RFC variant
    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($b), 4));
}

echo uuidv4(); // e.g. 9b2f3c1e-6a4d-4e8b-b1f0-2c7d5a9e3f64

random_bytes() uses the operating system’s secure random source, so these IDs are safe to use as public identifiers. For v7, parsing and database helpers, a library is still the better choice.

Don’t use uniqid() for UUIDs

uniqid() returns 13 hex characters built from the current time in microseconds. It isn’t a UUID, it isn’t random, and the PHP manual warns that it doesn’t guarantee unique values. Two requests in the same microsecond, or on two servers, can get the same value. Use random_bytes() or a UUID library instead.

Symfony alternative: symfony/uid

composer require symfony/uid
use Symfony\Component\Uid\Uuid;
use Symfony\Component\Uid\UuidV4;
use Symfony\Component\Uid\UuidV7;

$v4 = Uuid::v4();
$v7 = Uuid::v7();
$v5 = Uuid::v5(Uuid::NAMESPACE_URL, 'https://example.com');

echo (string) $v7;
echo $v7->toBase32();    // Crockford base32 (ULID-style encoding)
echo $v7->toBase58();    // shorter still

symfony/uid has been part of Symfony since 5.1. UuidV7 arrived in Symfony 6.2. The component has a smaller surface area and fits if you’re already on the Symfony stack.

Laravel

Laravel ships with first-class UUID support via traits:

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

class User extends Model
{
    use HasUuids;
}

HasUuids (Laravel 9.30.1+) fills id on insert. It does not make the column a UUID — the migration below does that with $table->uuid('id'). From Laravel 9.30.1 through 11.x the trait calls Str::orderedUuid(), a time-ordered UUID, not a plain v4. Laravel 12 and later generates UUIDv7 from HasUuids, and HasVersion4Uuids is the opt-out that keeps the Str::orderedUuid() behaviour of 9.30.1–11.x. Override newUniqueId only on 9.30.1–11.x when you want v7:

class User extends Model
{
    use HasUuids;

    public function newUniqueId(): string
    {
        return (string) \Ramsey\Uuid\Uuid::uuid7();
    }
}

Migration:

Schema::create('users', function (Blueprint $table) {
    $table->uuid('id')->primary();
    $table->string('email')->unique();
    $table->timestamps();
});

Symfony / Doctrine ORM

use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Types\UuidType;
use Symfony\Component\Uid\Uuid;

#[ORM\Entity]
class User
{
    #[ORM\Id]
    #[ORM\Column(type: UuidType::NAME, unique: true)]
    private Uuid $id;

    public function __construct()
    {
        $this->id = Uuid::v7();
    }
}

For ramsey/uuid + Doctrine, use the ramsey/uuid-doctrine adapter.

Database storage

For PostgreSQL: use uuid (native), 16 bytes.

For MySQL 8+: use BINARY(16) and convert with UUID_TO_BIN / BIN_TO_UUID. Both ramsey/uuid and symfony/uid have helpers for this:

$bytes = $id->getBytes();          // 16 raw bytes — ready for BINARY(16)
$id = Uuid::fromBytes($bytes);     // round-trip

Don’t store as VARCHAR(36) — see SQL UUID.

JSON serialization

$id = Uuid::uuid7();
echo json_encode(['id' => $id]);
// {"id":"01928a47-3b30-7c5e-9d1a-f0b8c4a7e923"}

Both libraries implement JsonSerializable. The default form is canonical hyphenated.

Validation in HTTP routes

Laravel:

Route::get('/users/{id}', function (string $id) {
    abort_if(!\Ramsey\Uuid\Uuid::isValid($id), 400);
    // ...
})->where('id', '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}');

The where constraint validates at the routing layer — invalid UUIDs return 404 before your handler runs.

Symfony:

#[Route('/users/{id}', requirements: ['id' => Requirement::UUID])]
public function show(Uuid $id): Response
{
    // $id is already a Uuid instance, validated
}

Performance

ramsey/uuid is sufficient for typical web throughput. If the math backend shows up in a profile, the library recommends enabling the GMP and BCMath extensions.

Common pitfalls

FAQ

Does PHP have a built-in UUID function?

No. PHP’s core has no UUID function, so use ramsey/uuid, symfony/uid, or the random_bytes() snippet above for a quick v4. Looking for a PHP GUID? It’s the same thing. See UUID vs GUID.

Which PHP UUID library should I use?

Use ramsey/uuid in plain PHP and Laravel projects, and symfony/uid (Symfony\Component\Uid\Uuid) if you’re already on Symfony. Both generate v4 and v7 and handle conversion to bytes for the database.

How do I generate a UUID in Laravel?

Call Str::uuid() for a v4 string, or add the HasUuids trait to a model so new rows get a UUID primary key automatically.

Should I use UUID v4 or v7 in PHP?

Use v7 for database primary keys, because its time ordering keeps indexes compact. Use v4 for tokens and IDs where you don’t want creation time to show.

How do I store a ramsey/uuid in a Doctrine entity?

Install ramsey/uuid-doctrine and register its type, then map the column with #[ORM\Column(type: 'uuid')]. Use the uuid_binary type instead if you want MySQL BINARY(16) storage. On Symfony, symfony/uid with UuidType (shown above) does the same job without the adapter.

Cheat sheet

GoalCode (ramsey/uuid)
RandomUuid::uuid4()
Time-orderedUuid::uuid7()
DeterministicUuid::uuid5(ns, name)
ParseUuid::fromString($s)
ValidateUuid::isValid($s)
Bytes for DB$id->getBytes()

Try the tools