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

tomirons's avatar

Route Model Binding with Route::controller

I've got the following routes:

Route::controllers([
    'auth' => 'Auth\AuthController',
    'password' => 'Auth\PasswordController',
    'admin' => 'AdminController',
    'site' => 'SiteController'
]);

And then I've got the following method in the SiteController:

/**
 * Get site details and pass to view
 *
 * @param Site $site
 * @return mixed
 * @internal param $site_id
 */
public function getDetails( Site $site )
{
    return $site;
}

When I go to the URL site.com/site/details/13 it doesn't return the site object.

I've added $router->model( 'one', 'App\Site' ); into the RouteServiceProvider and it works, but what if later down the road I want to add another controller like this but use it for jobs, and use the getDetails method again and pass through the App\Job object? It will automatically send the App\Site model instead cause of the {one} wildcard. I'd rather not have to manually route each get and post either.

So is there a way I can prevent this from happening?

0 likes
7 replies
michaeldyrynda's avatar

The route model binding is handled from the routes file, not from the controllers themselves..

# routes.php

// Name your variable placeholders nicely so you don't get collisions between concerns.
Route::get('/site/details/{site_id}', [ 'as' => 'site.details', 'uses' => 'SiteController@details', ]);

# RouteServiceProvider.php

public function boot(Router $router)
{
    // You bind the App\Site::find('{site_id}') from your route.
    // If you don't define the route explicitly - as with controller routing - this isn't going to work
    // because the placeholder ({site_id}) has not been defined anywhere.
    $router->model('site_id', Site::class);
}


# SiteController.php

use App\Site;

    // ...

    public function details(Site $site)
    {
        return $site;
    }

It's probably best to avoid implicit routing, given you're only going to run into more complications as your application grows.

As for routing individual get or post methods, you can group concerns to cut down on keystrokes a bit, but being explicit helps to use your routes file as something of documentation for your application.


# routes.php

Route::group([ 'prefix' => 'site', 'as' => 'sites::', ], function () {
    // route('sites::store');
    // POST /sites
    post('/', [ 'as' => 'store', 'uses' => 'SiteController@store', ]);

    // route('sites::create');
    // GET /sites/create
    get('create', [ 'as' => 'create', 'uses' => 'SiteController@create', ]);

    Route::group([ 'prefix' => '{site_id}', ], function () {
        // route('sites::update', $id);
        // PUT /sites/{site_id}
        put('/', [ 'as' => 'update', 'uses' => 'SiteController@update', ]);

        // route('sites::delete', $id);
        // DELETE /sites/{site_id}
        delete('/', [ 'as' => 'delete', 'uses' => 'SiteController@delete', ]);

        // route('sites::details', $id);
        // GET /sites/{site_id}/details <- (subjectively) better as you can group routes more easily
        get('/details', [ 'as' => 'details', 'uses' => 'SiteController@details', ]);
    });
});

Now, if you're being explicit with your application routes in your routes.php file, you can see which routes are set for your whole application, without trawling through your app controllers to see what mystery routes lie therein.

michaeldyrynda's avatar

Yep and in that video, you'll note that in order for route model binding to work, you need to define some key on which to bind, which you can't do when you use Route::controllers.

You can set the as key on any of the route methods - that is used so you can easily reference the route itself (route('sites::edit', $id);) in your views or controllers, without having to worry about the path itself changing.

If you're worried about a long routes file, you can do one of two things - require in each component, depending on how big your routes file is, or run php artisan route:cache, which will compile the routes file down to a serialised string.

Ultimately, it's not that big a deal. Trying to condense the routes file itself is absolutely premature optimisation.

Further reading.

tomirons's avatar

@deringer I have a controller that has about 12 methods, 6 get and 6 post. Listing all of these one by one would become a huge pain in my opinion. Or is this something I should have done from the beginning?

pmall's avatar

Listing all of these one by one would become a huge pain in my opinion.

Route-model bindings and route controller are just shortcuts for prototyping. Any serious application ends up removing them.

michaeldyrynda's avatar

@Hulu have your editor do the work for you. Setup snippets / live-templates if you think typing routes out by hand, but controller routing just buries routes where they're trickier to locate.

Please or to participate in this conversation.