Search object by slug and not by id

Roxy Walsh picture Roxy Walsh · Dec 27, 2015 · Viewed 22.7k times · Source

I'm a relative beginner with Laravel (using version 5.2.3) and have been working through tutorials on Laracasts and then doing a bit of my own experimenting.

I successfully set up a route that fetches an item from a table by its ID, as shown below

Route::get('/wiseweasel/{id}', 'WiseweaselController@singleArticle');

For simplicity, the controller simply dd's the article

public function singleArticle($id)
{
  $article = ww_articles::find($id);
  dd($article);
}

This works absolutely fine - I visit eg /wiseweasel/2 and get the contents of the record with id2.

So, I then wanted to use the slug field from the record instead of the id. Since I know the ID method was working, I've tried just modifying this route and controller (also tried creating anew, neither worked) So I now have:

Route::get('/wiseweasel/{slug}', 'WiseweaselController@singleArticle');

and

public function singleArticle($slug)
{
  $article = ww_articles::find($slug);
  dd($article);
}

The slug for the second record is "secondarticle". So, visiting the url /wiseweasel/secondarticle, I would expect to see the same record as previously dd'd out. Instead, I end up with null.

Even more oddly, using the original id route (/wiseweasel/2) still returns the record... when I have removed all trace of this from the routes and controller, so I would expect this to fail...

This is making me wonder if this could be some odd caching issue? I've tried

php artisan route:clear

in case the route was being cached. I've also tried restarting both Apache and MySql (I'm using XAMMP for both).

Still no luck though... not sure if I've misunderstood how something works or what's going on... so if anyone has any suggestions as to what I might have done wrong, or anything to try, I would be very grateful! :)

Answer

lagbox picture lagbox · Dec 27, 2015

You also have the option of using Route Model Binding to take care of this and inject the resolved instance into your methods.

With the new implicit Route Model Binding you can tell the model what key it should use for route binding.

// routes
Route::get('/wiseweasel/{article}', 'WiseweaselController@singleArticle');


// Article model
public function getRouteKeyName()
{
    return 'slug';
}

// controller
public function singleArticle(Article $article)
{
    dd($article);
}

Laravel Docs - Route Model Binding