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

Laravel Nova Hashids Laravel Package

pmochine/laravel-nova-hashids

Integrates Hashids with Laravel Nova so resource IDs are obfuscated in URLs and API responses. Hide sequential primary keys, prevent ID enumeration, and keep Nova links cleaner without changing your schema. Supports custom salts, minimum hash lengths, and easy configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

Version 3 is a hard requirement jump, so confirm the platform before anything else: Laravel Nova 5, Laravel 12 or 13, PHP 8.2+, and vinkla/hashids 13 or 14. Composer will refuse to install v3 next to Nova 3 or Nova 4, so on an older app you are choosing between upgrading Nova first or staying on v2 (and accepting the security issue below).

composer require pmochine/laravel-nova-hashids:^3.0
php artisan route:cache   # only if you cache routes

Register the card the same way as any Nova card — in NovaServiceProvider::cards() (or per-dashboard / per-resource) — and set the connection it should start on:

public function cards(): array
{
    return [
        (new HashidsCard())->connection('main'),
    ];
}

Where to look first:

  1. config/hashids.php — the default connection and the connections array. The card's select is driven entirely by this, and only names present here are accepted by the API.
  2. The connection() method on the card — determines which connection is preselected when the card renders.
  3. Pmochine\LaravelNovaHashids\Contracts\Converter — the new extension point if you do not want Hashids at all.

The first real use case is the one the card was built for: drop it on a resource detail screen and it converts the current resource's id to a hashid immediately, so support/debugging work ("give me the public id for order 1042") becomes a copy button instead of a Tinker session. The reverse direction — paste a hashid, decode it to the numeric id — is the second daily use.

Implementation Patterns

Detail-page conversion as the default placement. The card now converts the resource id on load when it sits on a resource detail page. Put it in NovaServiceProvider::cards() with ->onlyOnDetail() (or in a resource's cards()), and the encode step is already done when the page renders. For dashboards, keep it in decode mode and treat it as a lookup tool.

One card instance per connection. connection() sets the first connection shown in the select; the user can still switch. If a model lives in a specific hashids connection, be explicit rather than relying on the default:

(new HashidsCard())->connection('orders')->onlyOnDetail(),
(new HashidsCard())->connection('users')->onlyOnDetail(),

If the named connection does not exist, the card surfaces a warning instead of blowing up — useful during local setup, but treat that warning in staging as a config bug.

Swap the algorithm behind the Converter contract. Bind your own implementation in a service provider and the card keeps its UI while hashing however you like (ULIDs, short UUIDs, an in-house obfuscator):

$this->app->bind(
    \Pmochine\LaravelNovaHashids\Contracts\Converter::class,
    \App\Support\UlidConverter::class
);

This is the cleanest way to keep hashid-shaped URLs consistent if the rest of the app has already moved off Hashids.

Update anything that talked to the card API directly. This only matters if you wrote custom Vue/JS around the card, but the request field selected is now connection and the response payload uses new field names. Any bespoke front-end hitting those endpoints needs the rename; nothing else in the package uses that API.

Operator workflow features worth telling your team about. Enter submits the conversion, the Copy hashid button writes to the clipboard, and errors render inline under the fields while leaving them usable — so a bad paste does not force a page reload.

Gotchas and Tips

Upgrade off v2 on Nova 4/5 even if you do not need the features. Since Nova 4 the nova middleware group no longer authenticates users, so on v2 a guest could list your configured connections and encode/decode ids. v3 adds Nova's Authenticate and Authorize middleware. After upgrading, access is gated by the viewNova gate — if you have users who could reach the card before but cannot open Nova, that is the intended new behaviour, not a regression.

Remove your array_has() polyfill. If you added a global helper to work around issue #2, v3 no longer calls it. Leaving it in is harmless but it is dead code that will confuse the next person.

Do not name a connection 0. The Hashids manager resolves that name to the default connection, so the card refuses to show it and you will chase a "missing connection" that is actually configured.

Dotted connection names are now rejected. main.salt used to pass validation and then 500 inside the manager; now the API accepts only exact configured names. If you have config keys with dots, split them.

Only single model ids are convertible. A hashid that decodes to more than one number is rejected by design. If you were relying on multi-value encoding for composite keys, that is not supported.

Ids travel as strings. Large model ids keep all digits and leading zeros no longer get read as octal by GMP (042). If you write your own client against the endpoints, send ids as strings too — sending a JS number is how you silently lose precision on bigint primary keys.

Server errors now surface in the card instead of redirecting the page. A misconfigured connection produces a message in the card and an entry in your Laravel logs. When a user reports "the card says something went wrong", check storage/logs/laravel.log for the underlying exception before assuming a front-end bug — Nova.request() used to navigate away on 500, which is why this used to look like a random logout.

Vue 3 rebuild means old styling hacks are gone. The Vue 2 components and the Sass file were removed. If you were overriding those Sass variables or targeting old component classes in custom CSS, those selectors are now dead. Any real customisation should go through the Converter binding or a fork built with laravel/nova-devtool and Mix 6, which is how the package itself is built and tested (PHPUnit + Vitest).

German translations ship in-box for both the card and the API messages. If you maintain your own translations, check for collisions in your lang/vendor directory after the upgrade.

After composer require, re-run php artisan route:cache if you cache routes — the card's routes picked up new middleware, and a stale route cache is a classic source of "it still behaves like v2".

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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator