Product Decisions This Supports
- Feature scope: external identifiers. Supports shipping customer-facing URLs, share links, and public API resources that reference records by an opaque public ID rather than the auto-increment primary key — a common product requirement for anything users can copy, bookmark, or share.
- Build vs. buy vs. hand-roll. The decision is small but real: adopt a maintained MIT trait, write a 30-line internal trait, or move to UUID/ULID primary keys. This package sits in the "convention you adopt cheaply" bucket, not a platform bet.
- Roadmap sequencing. Best evaluated before tables and APIs proliferate. Retrofitting public identifiers onto live tables means backfills, dual-read logic, and URL migration — so the relevant roadmap decision is "do we standardize on an external-ID pattern in the next schema milestone?" rather than "do we install this today?"
- Privacy / data-exposure posture. Sequential IDs leak volume (customer counts, order counts, growth rate) and invite enumeration/scraping of adjacent records. A public-ID convention is a cheap, visible hardening control that supports security review and disclosure narratives.
- API surface design. Informs whether internal IDs are ever returned to clients, whether pagination cursors expose them, and whether support/ops tooling can map public → private IDs.
- Use cases it unlocks: tenant-safe resource URLs, public sharing links with revocable identifiers, partner integrations that shouldn't see internal keys, demos/portals where record count is commercially sensitive.
When to Consider This Package
Adopt when:
- You are on Laravel 9+ with Eloquent and want public IDs on a handful of models (users, orders, invoices, documents) without touching primary keys.
- You want a zero-dependency, MIT-licensed trait and accept owning a ~small surface area you could replace in an afternoon.
- Your team values speed over bespoke design and the pattern is already understood (external ID column + lookup on route model binding).
- You are in an early schema phase where adding the column and contract now is nearly free.
- You want one consistent internal convention rather than each team picking UUIDs, hashids, or random strings.
Look elsewhere or reconsider when:
- You need identifiers to be non-enumerable by construction (e.g., hashids/sqids-style reversible-but-obscured IDs) or cryptographically unpredictable at scale — validate the generator's entropy and collision behavior yourself.
- You want UUID/ULID as the primary key — use Laravel's built-in
HasUuids/HasUlids instead of a parallel public-ID column.
- Maintenance and community signal matter to your org. This repository has 0 stars, 0 dependents, and a single-maintainer profile; treat it as source you vendor rather than a supply-chain dependency. Fork it, pin it, or reimplement it internally.
- You need distributed-ID guarantees, key-rotation, or ID versioning — out of scope.
- You are not on Laravel/Eloquent or need framework-agnostic behavior.
- You require long-term support contracts or security SLAs — a hobby-scale package cannot provide them.
Practical adoption gate: read the source (it is small), confirm it handles collision retries and unique-index conflicts, verify index coverage on the public-ID column, and decide in writing whether you are depending on the package or copying the pattern into your own base model.
How to Pitch It (Stakeholders)
To executives (one paragraph): This is a small, low-cost hardening and product-quality step. It lets us expose records in URLs and APIs using an opaque public identifier instead of our internal database keys — which today would leak how many customers, orders, or records we have, and make it easy to guess and scrape neighboring records. The cost is minimal and reversible; the benefit is a cleaner security and privacy story plus shareable, stable links for customers. I recommend we adopt it as an internal convention rather than a strategic dependency.
To engineering: One trait on Eloquent models, Laravel 9+, no new runtime dependencies, MIT. It keeps primary keys internal and adds a public-ID column we control. The package is tiny and thinly maintained (no stars, no known dependents), so we should vendor/fork it or reimplement the ~one screen of logic internally and keep the interface identical — that gives us the convention without the supply-chain risk. Budget roughly a day to review the source, add the column and unique index, wire route-model binding, and decide the generation strategy (random vs. ULID).
Recommended decision: Adopt the pattern now, treat the package as optional. Standardize public IDs in the next schema milestone; implement behind an internal trait so we can swap the source later without touching models or routes.