phplaraveleloquentlaravel-8route-model-binding

How to change Route Model Binding finding data from id to slug


I have a route like the following.

Route::get('/articles/{articleSlug}' , 
    [App\Http\Controllers\ArticleController::class, 'single']);

And the method of single() at ArticleController class goes here:

public function single($slug)
{
    $article = Article::where('slug',$slug)->first();
    $article->increment('viewCount');

    return view('home.article',compact('article'));
}

Now I wish to use Route Model Binding for finding this data from the articles table based on the column slug. But as I know, Route Model Binding finds data based on the id. So how to change Route Model Binding finding data from id to slug ONLY for ArticleController.php (meaning that the other Controller classes can work with id as route model binding)?


Solution

  • In case you want to use other model field as the biding attribute instead of id you can define a getRouteKeyName which return the name of the field which must be use

    class Article extends Model {
        // other methods goes here
        public function getRouteKeyName() {
            return 'slug';
        }
    }
    

    Or you can pass the field name directly when you define the route like this

    Route::get('/articles/{article:slug}' , [App\Http\Controllers\ArticleController::class, 'single']);
    

    With this code inside of your controller you must ensure that the name provide as parameter in the route definition match the name of the controller argument

    public function single(Article $article)
    {
        $article->increment('viewCount');
    
        return view('home.article',compact('article'));
    }