Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jsphpndr's avatar

$user works in one route but returns undefined in another

I have this function set up in my controller:

    public function show($user) {

        $user = User::findOrFail($user);
        $institutions = Institution::orderBy('name')->get();

        // THIS WORKS
        if (auth()->user()->id === $user->id OR Auth::user()->hasRole('client')) {
            return view('agents.front.show', compact('user', 'institutions'))->with([
                'user' => $user,
            ]);
        }
        
		// THIS DOESN"T
        if(Auth::user()->hasRole(['admin', 'staff'])) {
            return view('dashboard.agents.show', compact('user'))->with([
                'user' => $user,
            ]);
        } else {
            abort(404);
        }

    }

In the first instance, I have no problem, everything comes back fine... in the second the view returns "Undefined variable $user".

It makes no sense. My routes are as follows:

// THESE WORK
Route::group(['prefix' => 'portal/c', 'middleware' => ['auth', 'role:client', 'App\Http\Middleware\PreventBackHistory']], function() {

    Route::get('lenders/lender/{user}', 'App\Http\Controllers\AgentController@show')->name('client.lender.show');
    
});


Route::group(['prefix' => 'portal/l','middleware' => ['auth', 'role:agent', 'App\Http\Middleware\PreventBackHistory']], function() {

    Route::get('/', 'App\Http\Controllers\AgentController@index')->name('index.l');

    Route::group(['prefix' => 'lenders'], function(){
    // Route::get('lender/{user}', 'App\Http\Controllers\AgentController@show')->name('agent.show');
    Route::get('lender/{user}/edit', 'App\Http\Controllers\AgentController@edit')->name('agent.edit');
    Route::patch('lender/{user}', 'App\Http\Controllers\AgentController@update')->name('agent.update');
    
    });

}); 


// THIS DOESN'T WORK
Route::group(['prefix' => 'dashboard', 'middleware' => 'role:staff|admin|superAdmin', 'App\Http\Middleware\PreventBackHistory'], function() { 

    // -- Lenders --//
    Route::group(['prefix' => 'lenders'], function() {

        Route::get('/', 'App\Http\Controllers\AgentController@index');
        Route::get('lender/create', 'App\Http\Controllers\AgentController@create');
        Route::get('s', 'App\Http\Controllers\AgentController@store');
        Route::get('lender/{ user }/edit', 'App\Http\Controllers\AgentController@edit');
        Route::get('lender/', 'App\Http\Controllers\AgentController@show')->name('lender.show');

    });
}); 

How can $user work for one but not the other?

0 likes
6 replies
tykus's avatar

Which route(s) are you speaking about? Also, why do you pass user to the view(s) using the compact and with approaches?

jsphpndr's avatar

@tykus, edit and show are not working.

Also, the compact, I think it's from an earlier approach.

tykus's avatar

@jsphpndr your show route has no wildcard placeholder for the $user parameter; the edit wildcard has spaces ({ user }) for some reason?

jsphpndr's avatar

@tykus, I'm not sure I understand how the wildcard is supposed to work when I'm trying to access a unique id.

Please excuse my ignorance.

tykus's avatar

@jsphpndr whenever you define a Route, you specify a URL, and within that URL (if relevant) you can set a placeholder for a dynamic ID using the wildcard e.g. {user} below:

Route::get('lender/{user}/edit', 'AgentController@edit')->name('lender.edit');
Route::get('lender/{user}', 'AgentController@show')->name('lender.show');

By convention, this placeholder expects the ID of the Resource (Model) which is the parameter passed into the Controller action:

 public function show($user)
{
    $user = User::findOrFail($user);
    // ... etc
}

 public function edit($user)
{
    $user = User::findOrFail($user);
    // ... etc
kokoshneta's avatar

@jsphpndr Consider that your lender.show route will match the exact URL /dashboard/lenders/lender/ – nothing else. How is the show() method supposed to know which user you want to pass along to the view? There’s nothing in the URL that indicates a user ID anywhere.

That’s what the wildcard is for – {user} in the URL means ‘this is where to put the user ID that the method will use to actually load the model’, so the route will match /dashboard/lenders/lender/123, for example. With your current routes, going to /dashboard/lenders/lender/123 will give you a 404 error, since there’s no route that matches that URL.

———

As an aside, your URLs could do with standardising. There’s no reason for the extra /lender part of your create, show and edit URLs – normal Laravel (and REST) naming conventions would be just /dashboard/lenders/create, /dashboard/lenders/{user} and /dashboard/lenders/{user}/edit. And /dashboard/lenders/s is an odd URL for storing – not to mention that the URL for storing something should not be defined as a GET request, only POST.

But you don’t need to do all this yourself – just declare your route as a resource route and Laravel will take care of creating the correct (standard) URLs and route names:

Route::group(['prefix' => 'dashboard', 'middleware' => 'role:staff|admin|superAdmin', 'App\Http\Middleware\PreventBackHistory'], function() { 
	Route::resource('lenders', App\Http\Controllers\AgentController::class)->parameters(['lender' => 'user']);
});

It looks like you already have all the correct method names in your controller to function as a resource, so take advantage of what the framework offers you.

Using a resource route, the parameter passed along to the show() and edit() methods will be $lender by default, but your controller methods expect their parameter to be called $user. The ->parameters(['lender' => 'user']) part above makes sure that the parameter gets passed along with the name $user so your methods will correctly intercept it.

Please or to participate in this conversation.