I have routes with user binding like
Route::get('users/{user}/posts', [PostController::class, 'index']); Route::get('users/{user}/comments', [CommentController::class, 'index']);
So I can use /users/1/posts
, /users/5/posts
etc, and in controller it’s automatically available thanks to model binding
public function index(User $user) { dd($user); }
But for current logged user I want to make possible to also use /me/
instead ID, like /users/me/posts
Is there a way to make it without defining separate controller methods where I would have to find user manually, and without duplicating all routes? So is it possible to “extend” default Laravel model binding globally?
Advertisement
Answer
I believe using a fixed route parameter like this is the most sustainable solution, especially if this is a shared code base. It will involve some repeated code, but makes it immediately clear what routes are available. And you can predefine the grouping callback to avoid repeating the route definitions.
$routeGroup = function ($r) { $r->get('posts', [PostController::class, 'index']); $r->get('comments', [CommentController::class, 'index']); }; Route::prefix('users/{user}')->group($routeGroup); Route::prefix('users/me')->group($routeGroup);
And then make the parameter optional in your controller method.
public function index(User $user = null) { $user = $user ?? Auth::user(); dd($user); }
Another possibility is overriding the resolveRouteBinding
method on your model. If you go with this method (or Patricus’ solution) I’d suggest leaving comments in the route file explaining what you’ve done.
class User extends Model { public function resolveRouteBinding($value, $field = null): ?self { return $value === 'me' ? Auth::user() : parent::resolveRouteBinding($value, $field); } }