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

Hash Ids Bundle Laravel Package

jasonbradley/hash-ids-bundle

Symfony bundle wrapping the hashids library to encode numeric IDs into short, reversible, non-sequential hashes—useful for hiding database IDs in URLs and public APIs. Adds service and Twig integration for encoding and decoding throughout a Symfony app.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony2 bundle, not a Laravel package, and the last release was August 2015. Treat it as a reference implementation rather than something you composer require into a Laravel app. If you're evaluating it, open these files first:

  1. DependencyInjection/Configuration.php — shows the actual config keys exposed (salt, min length, alphabet).
  2. DependencyInjection/*Extension.php — shows the service id and how the underlying Hashids\Hashids instance is constructed.
  3. Resources/config/services.yml — the service definition you'd otherwise write yourself.

The bundle is a thin container wrapper around hashids/hashids. There is no Laravel service provider, no facade, no config publishing, and its Symfony DI constraints will not resolve on modern Symfony or Laravel.

For a Laravel project, the minimal equivalent is:

composer require hashids/hashids
// AppServiceProvider::register()
$this->app->singleton(\Hashids\Hashids::class, fn () => new \Hashids\Hashids(
    config('app.hashids_salt'),
    (int) config('app.hashids_min_length', 8),
    config('app.hashids_alphabet', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890')
));
$hashids = app(\Hashids\Hashids::class);
$slug = $hashids->encode($post->id);      // "NkK9"
$ids  = $hashids->decode($slug);          // [123]

First use case: replacing sequential IDs in public URLs (/posts/123 → /posts/NkK9) so records can't be trivially enumerated. It is obfuscation, not authorisation — never rely on it as an access control.

Implementation Patterns

Route model binding. Laravel's implicit binding won't decode hashes. Add resolveRouteBinding() on the model, or a small HashidRouteBinding trait that decodes, validates the result is an array with exactly one element, and returns $this->findOrFail($ids[0]). Always return a 404 on a malformed hash rather than letting decode() return [].

Composite IDs. Hashids' real advantage over a simple base64 is that encode($userId, $postId) produces one opaque token that decodes back to both values. Use this for signed-ish share links where you need two identifiers but don't want two query params.

Presentation layer. Register a Blade directive or a Hashids facade rather than calling app() in views:

Blade::directive('hashid', fn ($id) => "<?php echo app(\Hashids\Hashids::class)->encode($id); ?>");

API resources. If you expose hashed IDs publicly, map them consistently in JsonResource::toArray() so every endpoint returns the hash and never the raw integer. Mixing the two leaks the sequence.

Environment-scoped salts. Put the salt in config/app.php driven by HASHIDS_SALT, and give staging/production different salts. Do not check the salt into the repo.

Symfony bundle specifics (if porting). The bundle exposes a single service; usage from a Symfony2 controller was $this->get('hash_ids')->encode($id) (confirm the exact id in services.yml, it may be namespaced like jasonbradley.hash_ids). Its only extension point is parameter/definition overrides in config.yml, i.e. the salt and minimum length.

Gotchas and Tips

Changing the salt invalidates every existing hash. Any URL, email, sitemap entry, or cached page containing a hash silently breaks. Treat the salt as append-only infrastructure: version it, and if you must rotate, keep the old encoder around to decode legacy values before re-encoding.

min_length is cosmetic. It pads output; it does not add security or guarantee collision-freedom. The library is deterministic — the same integer always yields the same hash for a given salt/alphabet. Uniqueness is inherited from the integer, not the hash.

Alphabet must be at least 16 characters and must not contain spaces. An invalid alphabet throws rather than silently defaulting, so validate it in a config test.

decode() always returns an array, even for a single integer. Code that does (int) $hashids->decode($hash) will work by accident on one element and fail on composites. Use $ids[0] ?? null explicitly.

Hashes are guessable by design. Hashids is reversible by anyone who knows the salt, and the salt sits in your app config. Anyone with source access (a contractor, a repo leak) can enumerate your entire ID space. Do not use it in place of signed URLs (URL::signedRoute) or policies for anything sensitive.

Unmaintained dependency chain. The bundle pins Symfony 2.x and old Hashids versions; Composer will refuse to install it alongside Laravel. Even the standalone hashids/hashids package is feature-frozen — it works, but expect no fixes. Budget a few lines to vendor your own wrapper rather than relying on either.

Debugging tip: reproduce issues outside the framework first (php -r 'var_dump((new Hashids\Hashids("x"))->decode("..."))'). Nine out of ten "my IDs changed" reports are a config-cache problem — run php artisan config:clear after touching the salt, since a cached config will happily keep serving the old value.

Extension points: in Laravel, bind Hashids\Hashids to an interface and inject that, so tests can swap in a fixed-salt instance. In the Symfony bundle, the only lever is overriding the service definition in your app config.

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