eig/eloquent-uuid
A Laravel package that lets Eloquent models use UUID primary keys instead of auto-incrementing integers. Drop it into existing models to generate unique, non-sequential IDs automatically for safer, distributed-friendly records.
Public identifier strategy — opaque IDs without re-architecting. The core product call is whether customer-facing resources expose sequential integers or non-enumerable UUIDs. This package implements that decision in roughly three lines of model code: a trait hooks Eloquent's creating event, generates a UUID, and flips $incrementing = false / $keyType = 'string'. It is one cheap way to execute the decision — the decision itself is the valuable part.
API contract durability. Committing to stable, non-guessable identifiers in public APIs, webhook payloads, and deep links lowers the cost of future migrations, prevents trivial resource enumeration, and keeps route-model binding working unchanged (the route key is the UUID). Real security and product benefit, but not dependent on adopting this specific package.
Distributed, multi-tenant, and merge/import use cases. Client-generated IDs, offline-first mobile sync, sharded writes, and merging records from acquisitions — anywhere a central auto-increment sequence becomes a coordination bottleneck. This is the strongest product justification for UUID keys.
Build vs. buy — the answer is increasingly "use native." Release 3.0.0 requires PHP 8 / Laravel 9.x, which is exactly the baseline where Laravel ships HasUuids and HasUlids natively. The release narrows the package's addressable case to the one configuration where it's least needed. Residual value is trait ergonomics and a forkable ~40-line reference — not capability.
Dependency footprint as a roadmap input. 3.0.0 adds a runtime dependency on eig/UUID 2.5.x — a second package from the same single maintainer, 0 dependents, last release December 2022. Adoption means tracking two dependency lines through every framework major bump, not a hypothetical cost.
Roadmap sequencing and one-way doors. If UUIDs are planned for a new service or a v2 API, resolve the primary-key choice before schema freeze. Retrofitting UUID keys onto populated tables is effectively prohibitive — drop and rebuild every foreign key, rewrite referencing rows, coordinated downtime, broken downstream consumers. For existing apps, the recommended variant is an integer PK plus a public uuid column, which bypasses this package entirely.
Explicitly not supported decisions: storage format (char(36) vs binary(16)), index locality and write throughput, ordered-ID strategy (ULID / UUIDv7), or database-level defaults. Those are separate architecture calls. Read the 0.595 score, 59 stars, 0 dependents, and 2022 last release as insufficient evidence — not as "bad code."
Consider it when:
eig/UUID 2.x — 3.0.0 is the smallest step to a supported stack rather than a rewrite.id primary key, created exclusively through Eloquent (create, factories) — never through insert()/upsert()/query-builder bulk paths, which bypass the creating event entirely.Look elsewhere — specifically at Laravel's native HasUuids / HasUlids — when:
illuminate/* to 9.x; install either refuses or "works" untested. This is the default case and it disqualifies the package outright.HasUlids or UUIDv7 with binary(16) solves this; the package does not.binary(16) storage without model-layer casting work, a non-id primary key, or UUIDs on a non-PK column — the trait's guard behaviour here is not guaranteed.NULL keys.To executives: The business question is whether public-facing records should expose sequential integers — which leak volume, invite enumeration, and complicate future migrations — or opaque UUIDs. That's a decision worth making deliberately, once, before schema freeze on a new service. This package is a low-cost way to prototype that decision, but it does not survive a framework upgrade: it is pinned to Laravel 9, which left security support in February 2024, and pulls in a second single-maintainer dependency last released in 2022. Recommend we adopt the policy (UUIDs for public identifiers on new bounded contexts) and implement it with Laravel's built-in HasUuids/HasUlids. Net saving: one dependency line per framework bump, and security patches delivered with the framework.
To engineering: Treat this as a ~40-line reference trait, not a dependency. If a spike needs it, use it, verify getIncrementing() returns false and getKeyType() returns 'string' in tinker, and add a "migrate to native HasUuids or fork" item to the roadmap at the same time — not later. Do not apply it across every model: put UUID keys on the 3–5 genuinely public models (orders, invoices, api tokens, share links, webhooks) and keep integer PKs on join tables, audit logs, and high-throughput internals. Write that rule in an ADR so the next contributor doesn't grep it everywhere. Watch the known failure modes: bulk insert()/upsert()/seeders bypass the trait and silently produce NULL keys; never combine it with HasUuids on one model (two creating hooks racing on id); and decide char(36) vs binary(16) before schema freeze, because that's where the real index cost lives.
How can I help you explore Laravel packages today?