Reputation: 4390
I would like to be able to accept either a 40-character string ID /users/{id}
or the user's username /users/{username}
and then return the users.show
view.
Upvotes: 1
Views: 5248
Reputation: 24549
When I need to match certain patterns, I use the Route::pattern()
method in the top of my routes.php file. For example:
Route::pattern('userid', '[0-9]{40}');
Route::pattern('username', '[a-zA-Z0-9]+');
You can easily adapt that to use your own regular expression to match whatever you need and then you just create two routes to match the requests:
Route::get('/users/{userid}', 'UserController@showByUserID');
Route::get('/users/{username}, 'UserController@showByUserName');
Those two controller methods would get the user differently, but both would call the same view file and pass in the user.
Upvotes: 0
Reputation:
I would go about this with Explicit Route Model Binding.
To do this:
Use the Route::bind method to specify custom binding logic
To do this add the following code to the boot method of the RouteServiceProvider class.
Route::bind('user', function ($value) {
return \App\User::where('id', $value)->orWhere('username', $value)->first();
});
Set up your route for Route Model Binding
Route::get('/{user}', 'UserController@show');
Modify your controller to accept the bound model
public function show(User $user)
{
echo $user;
}
There's a couple of advantages here over the other answers:
Upvotes: 1
Reputation: 399
For those who are looking for the Laravel 5.3+ answer:
Jeffery Way talked about this in one of his laracasts; not sure which one though.
Basically, you can pass the username through a route like this:
// you will need to set this up so the route ('/user/{user}')
// matches the Model you're binding to -> App\<User>
// ('/user/{username}') will not work
Route::get('/user/{user}', function(App\User $user){
// $user should now be App\User
return view('user.show', compact('user'));
// access the user in the 'user.show' view
// like: $user->username
});
However, to make this work, you need to add this to the User class:
public function getRouteKeyName()
{
return 'username';
}
Otherwise this would only work if you passed the id of the user in place of the username -> /user/1
Upvotes: 2
Reputation: 4390
I have found another solution to this. I don't know which is better though. Hopefully the community can vote...
Within my UsersController.php I have:
public function show($id_or_username)
{
$user = User::where('id' , '=', $id_or_username)->orWhere('username', $id_or_username)->firstOrFail();
return View::make('users.show', compact('user'));
}
Upvotes: 2