August 31, 2015 11:10

Router binding in Laravel used in conjunction with middleware makes model management really easy. No more passing in IDs, loading models, and checking permissions for every controller method.

This example makes use of my ślimak slugged models package

class Album extends SluggedModel
{
    protected $appends = ['url'];

    /**
     * @return string
     */
    public function getUrlAttribute()
    {
        return '/albums/' . $this->slug;
    }
}

In app/Http/routes.php

Route::get('albums/{album}', 'AlbumController@show');
Route::get('albums/{album}/edit', 'AlbumController@edit');

In app/Providers/RouteServiceProvider.php

$router->bind('album', function ($slug) {
    return \App\Album::findBySlug($slug);
});

Finally, in your controller:

use App\Album;

class AlbumController extends Controller
{
    public function show(Album $album)
    {
        return view('albums.show')
            ->with('album', $album);
    }
}

Now when linking to your album's permalink in Blade, you can simply link to {{ $album->url }}. To link to the edit URL, just link to {{ $album->url }}/edit

This gets even more useful when you start to add middleware. For example, I can check to make sure only the album's owner, and admins, have permission to edit the album.

class Owner {
    public function handle($request, Closure $next, $resource)
    {
        $user = \Auth::user();

        if ($request->{$resource} && $request->{$resource}->user_id != $user->id && ! $user->is_admin) {
            abort(403);
        }

        return $next($request);
    }
}

Then if I add this middleware to the controller it takes care of that protection easily:

class AlbumController extends Controller
{
    public function edit(Album $album)
    {
        $this->middleware('owner:album');

        return view('albums.edit')
            ->with('album', $album);
    }
}

Laravel, PHP