I have a route like this:
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 wished to use Route Model Binding for finding this data from 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)?
CodePudding user response:
Your controller is already set up, all you need to do is change your variable name to $slug in the route, and I believe that should be enough:
Route::get('/articles/{slug}' , [App\Http\Controllers\ArticleController::class, 'single']);
CodePudding user response:
In your case in routes, you gave the variable {articleSlug}
, so in your Controller, you need to use the same variable name $articleSlug
.
Try like this:
public function single($articleSlug)
{
$article = Article::where('slug',$articleSlug)->first();
$article->increment('viewCount');
return view('home.article',compact('article'));
}
CodePudding user response:
change your route to this:
Route::get('/articles/{article:slug}' , [App\Http\Controllers\ArticleController::class, 'single']);
and then inject the Article model to your controller function and let laravel do the rest for you:
public function single(Article $article)
{
$article->increment('viewCount');
return view('home.article',compact('article'));
}
CodePudding user response:
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'));
}
CodePudding user response:
you can customize route model bindings directly in the route definition:
past given code in app/model/Article.php:
public function getRouteKeyName() { return 'slug'; }
2.when you use slug change route to
Route::get('/articles/{article:slug}' , [App\Http\Controllers\ArticleController::class, 'single']);
to use id sample change slug to id
Route::get('/articles/{article:id}' , [App\Http\Controllers\ArticleController::class, 'single']);
CodePudding user response:
you can add bind method to your model boot() like this
public function boot()
{
Route::bind('article', function ($value) {
return Article::where('slug', $value)->firstOrFail();
});
}
to learn more about it read this section in the Laravel docs https://laravel.com/docs/9.x/routing#customizing-the-resolution-logic