qopiku/filament-sqids
Filament plugin for Sqids: automatically encode and decode model IDs into short, obfuscated, URL-friendly strings. Integrates with Filament resources and tables to hide sequential primary keys while keeping routes and links clean and portable.
korfra/filament-sqids integrates Sqids (the Hashids successor) into Filament so resource URLs expose short, reversible, non-sequential identifiers instead of raw auto-increment keys. v0.1.0 is the first tagged release after 0.0.1, so treat the API as pre-stable and pin the version in composer.json.
Minimal setup:
composer require korfra/filament-sqids:^0.1
php artisan vendor:publish --tag="filament-sqids-config"
app/Providers/Filament/AdminPanelProvider.php):
->plugins([
\Korfra\FilamentSqids\FilamentSqidsPlugin::make(),
])
use Korfra\FilamentSqids\Concerns\HasSqids;
class User extends Model
{
use HasSqids;
}
First use case: open a Filament resource (e.g. UserResource) and visit the edit page. Instead of /admin/users/1/edit you should see the encoded segment (/admin/users/<sqid>/edit). If you see a 404, the trait is not applied or the panel plugin is not registered — check those two first before anything else. The package config file (config/filament-sqids.php) is the place to look next: it typically exposes min_length, alphabet, and blocklist, which are the knobs you will actually touch day-to-day.
Model-level encoding (single source of truth). Put the trait on the Eloquent model rather than encoding at the resource layer. That way route model binding, route('filament...edit', $user), and any getRouteKey() usage all stay consistent without per-resource wiring. The trait is expected to override getRouteKey() (returns the sqid) and resolveRouteBinding()/resolveRouteBindingQuery() (decodes then queries by primary key). Verify both are honoured on your Filament version — Filament v3 and v4 differ slightly in how resource route binding resolves models.
Scoping encoded segments to specific resources only. If you do not want every model encoded, apply the trait selectively. This is the safer rollout: enable it on one resource group, confirm URLs and deep links behave, then expand.
Generating URLs in custom actions and notifications. Once the trait is on the model, pass the model instance rather than the ID:
Notification::make()
->actions([
Action::make('view')
->url(UserResource::getUrl('edit', ['record' => $user])),
]);
Avoid building URLs from $user->id manually — that is the fastest way to reintroduce raw IDs into the UI.
Custom sqid columns / non-increment keys. If a model uses UUIDs or a slug already, the trait likely needs the underlying key to be numeric for Sqids to encode it. For non-numeric keys, prefer a dedicated numeric surrogate column or leave the model unencoded. Do not mix a UUID primary key with sqid encoding unless the package documents that path.
Relation managers and nested resources. Encoded route keys propagate through Filament's relation manager URLs because they reuse the parent record's route key. Test one nested resource (e.g. UserResource → PostsRelationManager) early; that is where route-key assumptions usually surface.
Testing. In feature tests, decode the URL segment with Sqids::decode() (or the package's helper, if exposed) to assert against the real primary key rather than hard-coding sqids — sqids are deterministic for a given alphabet/min_length, but hard-coded values become brittle the moment you change config.
canView/canEdit checks in place. If you need unguessable URLs, use UUIDs instead.alphabet, min_length, or blocklist changes every generated sqid. Bookmarks, emailed links, and cached pages will 404. Set the config once, before launch, and treat it as effectively immutable.min_length is a floor, not a fixed length. Sqids grow as the underlying number grows. Do not assume a fixed-length segment in route regex constraints or validation rules.resolveRouteBinding that accepts both forms.Sqids::decode($segment); // returns [] if the alphabet/blocklist rejects it
An empty array means the segment was generated with a different config or is genuinely invalid — not a route registration problem."korfra/filament-sqids": "0.1.*") and read the changelog before every bump. The 0.0.1 → 0.1.0 jump is the kind of release that can silently rename config keys or trait namespaces.How can I help you explore Laravel packages today?