NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Sluggable for Laravel

Route model binding

Route::get('/topics/{topic}', ShowTopic::class);                              // routeKey() column
Route::get('/posts/{post:seo_slug}', ShowPost::class);                        // any slug column
Route::get('/clinics/{clinic}/products/{product:slug}', ShowProduct::class)->scopeBindings();
Route::get('/archive/{topic}', ShowArchived::class)->withTrashed();
route('topics.show', $topic);                                                 // current-locale slug
  • routeKey() makes the column getRouteKeyName(); for a locale map getRouteKey() is the current-locale slug, so URL generation depends on the locale — queued URL generation should run under the intended locale.
  • Binding follows the definition’s chain (LocaleFallback::Any by default, so a URL in any resolvable locale still resolves) and prefers the current locale.
  • Scoped child bindings (->scopeBindings(), HasMany and BelongsToMany) and ->withTrashed() routes are covered.
  • Non-string, over-long or control-character values never reach the database.

Primary-key fallback

SlugDefinition::for('slug')->from('name')->routeKey()->bindByKeyFallback();
// /products/red-chair and /products/42 both resolve

bindByKeyFallback() (or binding.key_fallback globally) tries the primary key after a slug miss — and only for values shaped like the key: ctype_digit for integer keys, the model’s own uuid/ulid validation for unique ids. A numeric slug like 2024 is never shadowed by id 2024.

Composing with HasUuids / HasUlids

HasUuids and HasUlids also define resolveRouteBindingQuery, so resolve the conflict with insteadof — HasSlug keeps their malformed-id guard for key bindings:

use HasSlug, HasUuids {
    HasSlug::resolveRouteBindingQuery insteadof HasUuids;
}

A method declared on the model class itself silently wins over the trait — delete your own getRouteKeyName() / resolveRouteBinding() when adopting routeKey().

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.