Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Jaytee's avatar
Level 39

Route Model Binding

Hey guys, I've nearly really learned about Route Model Binding, the Service Container and Service Providers. I'm just starting to learn them now but I was wondering how exactly this works:

ProfileController

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

Routes:

Route::get('{user}', 'ProfileController@show')->name('profile.show');

RouteServiceProvider

public function boot(Router $router)
{
    parent::boot($router);

    $router->bind('user', function($value) {
        return User::where('username', $value)->first();
    });
}

How does this know which route this is for / how does this work?

I was also wondering how I could pass a custom error through as I've tried on the boot() method and the show() method.

Example: If a user isn't found with that username, return a custom error. At the moment, Laravel returns (No results for App\User.....).

Thanks

0 likes
6 replies
davestewart's avatar

I'm guessing that:

  • because the app knows what controller method to call (via routing)
  • it can find out what type (Eloquent) the first argument is (through reflection)
  • it just does a User::find($id)(the Eloquent parameter type) within the container, then
  • passes that, rather than the id (URL parameter) to your controller method

Remember that controllers are constructed and called by the app, so it (not you) is responsible for passing parameters.

If you hadn't type-hinted the argument, the app / router / whatever it is that calls the controller, would just pass the id (route parameter).

Also, did your route mean to just be '{user}' ? Would you rather not something like 'user/{user}' ?

dawiyo's avatar

You can throw an error by passing a closure as the 3 argument like this:

$router->model('user', function($value) {
    return User::where('username', $value)->first();
}, function() {
    throw new NotFoundHttpException;
});
Jaytee's avatar
Level 39

@davestewart

The full route is actually:

Route::group(['prefix' => '{user}'], function() {
    $this->get('/', 'ProfileController@show')->name('profile.show');
    $this->get('edit', 'ProfileController@edit')->name('profile.edit');
});

I prefer a user profile route to be:

example.com/{user}
// Than
example.com/user(or profile)/{user}

@dawiyo Thanks

Jaytee's avatar
Level 39

@davestewart Yeah I'm not a fan of having routes with /profile etc.

It's personal preferences, no right or wrong. :)

Please or to participate in this conversation.