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

Opaque Route Key Laravel Package

channor/opaque-route-key

Laravel package that swaps numeric route model binding keys for opaque, non-guessable identifiers, so URLs stop exposing sequential IDs. Simple setup, works with existing route model binding, and helps keep internal IDs and resource counts private.

View on GitHub
Deep Wiki
Context7

Getting Started

v2 is a breaking release of the opaque route key package — do not treat it as a drop-in minor upgrade.

  1. Check your compatibility first. Run composer why channor/opaque-route-key and grep your app for the legacy namespace:
    grep -rn "Channor\\\\HashedRouteKey" app/ config/ database/ tests/
    
    If you find hits and cannot migrate now, pin channor/opaque-route-key:^1.1 and defer.
  2. Upgrade with composer require channor/opaque-route-key:^2.0 and read docs/upgrade-v2.md before touching code — it is the canonical migration checklist for this release.
  3. Re-publish the config using the current publish tag (the legacy hashed-route-key tag is gone). Verify the file that lands is the v2 config, not a stale config/hashed-route-key.php left in the repo.
  4. Set your salt/key material explicitly in config or env. The HASHED_ROUTE_KEY_SALT fallback was removed in v2 — if you relied on it, the value is now silently ignored and all previously issued keys stop resolving.
  5. Swap the trait on your first model, clear php artisan config:clear (and optimize:clear on cached deploys), and hit a bound route.

Where to look first: the README quick-start for the current trait/facade names, then docs/upgrade-v2.md for the namespace and config remapping table. The first real use case is almost always the same: stop leaking sequential auto-increment IDs in URLs and route() output without hand-rolling a UUID column.

Implementation Patterns

Model-level opt-in. The package is designed to be applied per model via a trait, with auto_reserve_model_names kept at its false default. That means v2 does not auto-discover every model — you explicitly attach the trait and let route model binding do the resolution. A common mistake is assuming the new default reserves names for you; it doesn't, so keep the registration explicit if you depend on per-model key namespaces.

Route model binding is the primary integration point. The idiomatic flow is: trait on the model → Route::get('/invoices/{invoice}', ...) → the controller receives a hydrated model. Because the codec defaults and attempt-0 behavior are preserved in v2, keys generated before the upgrade should still round-trip (assuming an unchanged salt), which makes the migration mostly mechanical. Verify this with one known URL before rolling out.

API resources and link generation. Return the opaque key in resources rather than id, and drive all outbound URLs through route() so the key is generated consistently. If you're building URLs by string concatenation anywhere, those are the places that break silently on salt changes.

Validation. Prefer route binding over Rule::exists against the raw column — opaque keys are not database values, so an exists rule will reject valid input. Where you must validate early, validate the shape/decodability of the key rather than its presence in a table.

Migration sweep for v1 apps. Replace the legacy Channor\HashedRouteKey trait with the v2 equivalent in every model, then delete the old config/hashed-route-key.php so nothing reads a stale value by accident. Also audit composer.json for anything relying on the removed replace metadata — a package that previously satisfied a dependency through replacement will now surface as a duplicate or conflict on composer update.

Testing. Assert on decoded/bound results rather than hardcoded key strings where possible, but keep at least one golden-value test per model — it is the cheapest early warning that your salt or codec config drifted.

Gotchas and Tips

  • Silent 404s after upgrade are almost always salt-related. The removal of the HASHED_ROUTE_KEY_SALT env fallback means keys regenerate from a different source unless you explicitly carry the value into the v2 config. Symptom: routes bind fine for new records, every old bookmark 404s.
  • Config file rename is the number-one trap. v2 no longer reads hashed-route-key. If your deployment only ships the old file, the package falls back to defaults that likely differ from your intended salt.
  • Config cache on deploy. Any salt/config change is invisible until php artisan config:clear runs. On containerised deploys, confirm the cached config was rebuilt in the same layer that wrote the new file.
  • Publish tags changed. vendor:publish --tag=... with the legacy tag silently publishes nothing — no error, just a missing file.
  • Namespace removal is a hard fatal. Class "Channor\HashedRouteKey" not found at boot means one model was missed in the sweep. Static analysis or a repo-wide grep catches this before deploy.
  • auto_reserve_model_names is false. If your v1 config had it enabled via the legacy file, the behaviour quietly reverts. Confirm intent rather than assuming the old setting carried over.
  • Composer replace removal. If your app or a sister package depended on the replacement metadata to satisfy a constraint, resolve that explicitly before running composer update in CI — this surfaces as a dependency resolution failure, not a runtime one.
  • Debugging keys: decode a key to inspect its payload (attempt index, model marker) rather than squinting at the string. If you see a non-zero attempt value, you have a collision and should check that the reserved-name/model mapping is what you expect.
  • Extension points: the codec and key-generation path are the natural places to bind custom implementations if you need a different encoding or key length. Keep changes there until the migration is settled — customising the codec and changing the salt in the same deploy makes incidents much harder to untangle.
  • Keep a rollback plan. Because v2 removes the compatibility shim, rolling back to ^1.1 requires reinstating the old namespace and config. Decide the rollback boundary (and whether old URLs must keep working) before the production cutover.
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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core