Cleaner Laravel Controllers with Route Model Binding

Laravel as a framework either for building websites or a container to build APIs (lumen) has evolved as a developers framework of choice. Laravel comes with a lot of growing features - take for example Laravel's events. Events in Laravel used to be a simple pub-sub library, but now Laravel events can broadcast all the way to the client and allows us to [create realtime apps]https://scotch.io/tutorials/create-a-real-time-shoutbox-with-laravel-events).

Table of Contents

Route model binding in Laravel provides a mechanism to inject a model instance into your routes. Still not clear on the meaning, here is an example. Say we want to get a post from the database, we could do something like this:

...// the route parameter is the id of the post// for example http://example.com/posts/53Route::get('posts/{id}',function($id){// we have to find the post using the $id$post=Post::find($id);// if there is no post, 404if(!$post)returnabort(404);// return the view and the postreturnview('post.show',compact('post'));});...

We could further go on to simplify this method into

...// the route parameter is the id of the post// for example http://awesome.dev/posts/53Route::get('posts/{id}',function($id){// find the post or 404 if not found$post=Post::findOrFail($id);// return the view and the postreturnview('post.show',compact('post'));});...

But route model binding helps us get rid of extra keystrokes by simplifying both instances above into

...// by using $post, we can inject the Post objectRoute::get('posts/{post}',function($post){// we now have access to the $post object! no code necessary// return the view and the postreturnview('post.show',compact('post'));});...

This is made possible by telling Laravel to inject a Post model into any route controller that has a {post} parameter attached to it.

Laravel currently supports two types of route model bindings. We have:

Just like the name implies, you have to explicitly tell laravel you want it to bind a url parameter to a particular model. There are two ways to do this, we could bind a parameter to a model using the provided Route facade or carry out this binding in app/Providers/RouteServiceProvider.php (I prefer this method).

Free Node eBook

Build your first Node apps and learn server-side JavaScript.

📧

Nice!

Check your email to confirm your subscription.

Using the Route Facade

Using the Route facade to bind a parameter to a model, we can do somthing like this:

Route::bind('post','App\Post');

We could also give our binding more meaning, for example what if we want a post only if is a draft? For that we could change the second parameter of the Route::bind to a closure which takes the route parameter as its value.

Using the RouteServiceProvider

The only difference between using the Route facade and RouteServiceProvider class is that - registering your bindings is done in the boot method of the RouteServiceProvider class (location is app/Providers directory) and the bind method is called on the $router object injected into the method. Quick example

I build a lot of APIs, so custom exceptions for route model bindings is actually more useful for people like me. Laravel provides an easy way for us to do this. Still in the boot method of the RouteServiceProvider class, call the model method on the $router object.

The model method takes three arguments, the arguments are similar to that of the bind method, with a new addition the third argument which is a closure that throws the new exception.

From the moment you publish a website, you need to be wary of security. From hackers to script-kiddies, you can’t always be sure of where the next attack could come from. So, as developers, we are always on the prowl for the next best thing when it comes to protecting our website(s)....