26th Oct 17By John Doe

Working with a lot of endpoints and controllers, it’s nice to keep them clean as much as possible. Little solutions like Laravel’s route model binding helps us to keep our controllers cleaner.

Without Binding

Without the route model binding, generally our controller show method would look something like this:

// /users/{user}
public function show($id)
{
    $user = User::findOrFail($id);

    return view('profile', compact('user'));
}

As we see there is an extra line in our method, where we look up the relevant Eloquent model. We can automate this step by using the binding. We can do it on an explicit and implicit way.

Implicit Binding

The implicit way means we lean on the automatically generated route segments, which refers to the bound variable name as well. Let’s see an example of the previous show method.

// /users/{user}
public function show(User $user)
{
    return view('profile', compact('user'));
}

By type hinting the User Eloquent model, the framework knows what to resolve automatically. The route segment what it’s looking for is the {user} part, so the variable we need to give $user as the type hinted variable name.

If there is no record in the database with the given route key, it returns a 404 HTTP response automatically.

By default, the framework looks for the id column in our database. If we want to use another key for our binding,  we can customize it in our Eloquent models. All we have to do is to add the getRouteKeyName method to the model we want to modify.

getRouteKeyName()
{
    return 'slug';
}

Now the route key refers to the slug column in our database table rather than the id.

It’s good to know, Route Model binding is also working in our broadcasting routes. Test it out in your channels.php routes file.

Explicit Binding

If things are more complex, maybe we need some logic to solve our model instance. We can use explicit binding for that in our RouteServiceProvider‘s boot method.

public function boot()
{
    parent::boot();

    Route::model('user', User::class);
}

Now we can use type-hint where we want to. All we need to do to use the {user} route key in the where we want to bind our model. As in an implicit way, if there is no model with the route key – database column match, it will return with a 404 HTTP response.

To customize the logic we can use the bind method instead of the model method. In the boot method again:

Route::model('user', function ($value) {
    return User::where('column', $value)->firstorFail();
});

Summary

Route Model binding is a nice approach to keep the code a little bit cleaner. Of course don’t use it when it’s not relevant because it’s still an extra SQL query.

We think this is a nice help for REST applications even on web or API side. As an extra, it’s working in our broadcasting routes as well what can make our life easier as well when we are building a bigger real-time web socket based application.