Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Hashids Laravel Package

torann/hashids

Laravel wrapper for Hashids that encodes numeric IDs into short, unique, non-sequential strings and decodes them back, helping hide database IDs in URLs and APIs with configurable salt, length, alphabet, and simple Laravel integration.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Public identifier strategy — adopt, don't build. Every product with auto-increment keys eventually asks how to expose record IDs without broadcasting order volume and growth rate. torann/hashids answers it with a reversible, non-sequential encoding of integers, delivered as thin glue (service provider + Hashids facade + publishable config) under a BSD-2-Clause licence. The build-vs-buy calculation is not close: maintaining an in-house encoder buys nothing and costs maintenance forever.
  • Anti-enumeration as a scoped hardening requirement. When a security review, customer diligence questionnaire, or roadmap item says "predictable identifiers," this is the concrete, low-effort mitigation to attach to that ticket. Scope it explicitly as obfuscation, not authorization — no endpoint becomes safe because its ID is encoded, and the ticket should say so in writing so nobody later treats it as an access control.
  • Which surfaces to convert — a product scoping decision, not an engineering one. Candidate surfaces: share links, customer-facing order/invoice references, referral and coupon codes, API resource IDs, anything where a short copyable string beats a 36-character UUID. Explicit non-candidates: internal admin tooling, join tables, service-to-service identifiers. Encoding everything adds indirection with zero user-visible payoff; the PM should name the short list rather than let it sprawl.
  • URL and API-contract design without a schema migration. Because encoding is reversible, external handles can map to internal primary keys at the serialization boundary. That preserves optionality: the public handle stays an implementation detail you can later back with ULIDs or UUIDv7 without redesigning your public URLs.
  • Salt lifecycle as a user-visible product event. Rotating the salt invalidates every outstanding link, bookmark, emailed reference, and cached page simultaneously. That is a comms-and-recovery decision (where the salt lives, who can rotate it, whether dual-read via a second named connection is needed, what the user sees on a dead link), not a deploy step. A PM who doesn't own this policy will discover it during an incident.
  • Per-resource identifier policy via named connections. Coupon codes want short and human-typeable; tenant references want longer and non-guessable-looking. Multiple named connections with independent salt/length let one codebase serve different product surfaces — a cheap way to differentiate without forking the implementation.
  • Roadmap sequencing on framework upgrades. Release 3.0.6 adds Laravel 12 support as a patch, implying no migration cost for teams already on 3.x. Slot it into an existing Laravel 12 upgrade tranche rather than carving out a standalone project; teams on 2.x get nothing from this release and would need to read the 3.0.0 breaking changes first.
  • What this decision is explicitly not. Not a security boundary, not a substitute for authorization checks, and not the right answer where the requirement is genuine unguessability (use UUIDv7/ULID or a server-side opaque token) or sortable/ordered IDs (hashids destroys ordering). Saying this up front prevents the most expensive misapplication.

When to Consider This Package

Adopt when:

  • You expose public-facing integer primary keys and want to reduce enumeration risk with a change confined to the URL/serialization layer — no schema migration, no backfill, no data model change.
  • Your identifier requirement is short, copyable, read-aloud-friendly, and reversible, and the threat model is casual inference rather than targeted attack.
  • You are already on Laravel 11/12 with auto-discovery and want zero-config setup — publish the config, set the salt from an env var, done.
  • You can commit to a thin adapter boundary (a two-method PublicId::encode()/decode() wrapper). This is the single adoption precondition worth enforcing, because it converts every downstream risk — maintainer abandonment, salt rotation, alphabet change, eventual switch to ULIDs — into a one-file change.
  • You have a place to store the salt properly (secret manager per environment) and a deploy pipeline that re-runs config:cache.

Look elsewhere when:

  • The requirement is actual security. Invitation tokens, password resets, signed-URL substitutes, capability links, anything where possession grants access. Hashids are reversible by anyone holding the salt; a leaked salt in a repo, stack trace, or cache artifact makes every ID enumerable again.
  • You need unguessability without a shared secret. Use UUIDv7/ULID or random opaque tokens stored server-side.
  • You need ordering, range queries, or time-sortability on the public identifier. Hashids is deliberately non-sequential and destroys that.
  • You need fixed-width identifiers. length is a minimum that pads, not a fixed width that truncates — it grows with input. Any UI or char(10) column or {10} regex built on a fixed width will break at volume.
  • You need multi-value or hex ergonomics beyond the facade. Drop to the underlying hashids/hashids library through your adapter rather than fighting the wrapper.
  • Your supply-chain policy can't absorb a low-signal dependency. ~54 stars, one maintainer, no listed dependents, last release Jan 2026. The saving grace is that the wrapper is ~a service provider, a facade, and a config array — the fallback is genuinely cheap, provided you wrote the adapter first. Also verify the illuminate/* constraint in composer.json against your actual Laravel and PHP floor rather than trusting the release note.
  • You're on Laravel ≤10 without a planned upgrade path — you'd be pinned to an older 3.x or reading the 3.0.0 breaking changes for no benefit.

Adoption criteria worth stating as exit conditions: a named owner for the salt, a documented rotation runbook, a pinned test salt in phpunit.xml, and a written fallback plan (call hashids/hashids directly or fork the glue).

How to Pitch It (Stakeholders)

One line: A small, low-cost Laravel package that stops our public URLs from advertising how many orders, users, and invoices we've ever created — without touching the database.

For executives: Our customer-facing links currently look like /orders/10432, which tells anyone who clicks twice roughly how much we sell and lets competitors or scrapers walk our data. This package replaces those numbers with short opaque strings like k4Lx9mQ2bA7e at the edge of the application — no data migration, no downtime, no new infrastructure. It's a BSD-licensed library behind a thin adapter we control, so the switching cost if we ever change our minds is one file. The decision that matters is not technical, it's policy: we own the secret that makes these strings reversible, and rotating it is a customer-visible event, so we document it once and move on.

For engineering: It's a Laravel wrapper around hashids/hashids — a service provider, a Hashids facade (encode, decode, encodeHex, decodeHex, connection), and a publishable config for salt, length, and alphabet. Auto-discovery, zero config. Two implementation notes we're treating as requirements, not preferences:

  1. Wrap it. No Hashids:: calls in controllers. A PublicId::encode()/decode() adapter is the real extension point and the reason a future swap to ULIDs is a one-file change.
  2. Decode defensively. decode() returns an array and returns [] on garbage — never throws, never returns null. The adapter returns ?int so validation failures become clean 422s and route bindings become clean 404s.

Primary pattern is model route keys for the handful of publicly addressable models (Order, Invoice, Share) plus encoding in API resources — and never emitting the raw integer alongside the encoded one, or someone builds against it. Keep admin and service-to-service on plain integers. Pin the salt in phpunit.xml and assert on round-trips, not literals, so tests survive a salt change.

For the risk register: Single maintainer, low star count, no listed dependents. Mitigations already priced in: thin surface, adapter boundary, cheap documented fallback. Two gotchas that have burned teams before — env() only works inside config files (a runtime env() call silently becomes null once config:cache runs), and changing the alphabet in production has exactly the same link-breaking blast radius as rotating the salt, which people usually don't realize. Rollout on existing links should be additive: keep integer URLs resolving via a 301 to the encoded form, watch legacy-URL hit counts and 404 rates, and retire the redirect when the tail flattens.

Success measures: zero schema changes shipped, encoded identifiers live on the agreed surface list, a documented salt/rotation runbook owned by a named person, and a legacy-URL hit rate that decays to noise.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core