In this episode, we dive into a really practical Laravel tip: how to set up route model binding so it works with either an ID or a slug in your URLs. This means users (or your app) can visit a route like /courses/1
or /courses/some-slug
and get the same resource, whether they use the numeric ID or a readable string slug.
We start out by looking at the default route model binding behavior—in Laravel, it looks up a model using the primary key (usually the ID). That's fine, but it breaks when you try to pass a slug instead, because Laravel expects an integer.
First, we check out overriding the getRouteKeyName()
method on the model, but that just swaps between ID and slug—doesn't help if you want to support both.
The real solution? We jump into the RouteServiceProvider and set up a custom binding closure. Inside, we add some logic: if the incoming value is numeric, search by ID; otherwise, search by slug. We also look at using firstOrFail()
to keep things tidy and ensure the app returns a 404 if nothing is found (just like the default model binding).
By the end, you'll see how to make your routes flexible while keeping your code clean and easy to maintain. It's a simple change, but really useful!