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

pn523's avatar
Level 2

Help with Gate::before

I am using laravel 7.x

Gate before method is not called, I do not get $user.

Following is the code in AuthServiceProvider :

Gate::before(function ($user) {
            dd($user);
            if ($user->id == '2') {
                return true;
            }
            else{
                return false;
            }
        });
0 likes
31 replies
Armani's avatar

Did you run :

php artisan ui bootstrap --auth

I mean do you have Login and Registration system?

pn523's avatar
Level 2

Yes I already have auth setup and it works as expected

Sinnbeck's avatar

Are you using a gate on the route?

And you can simplify that code alot

Gate::before(function ($user) {
    return $user->id == 2;
});
pn523's avatar
Level 2

UPDATE :

When I run dd(Auth::user()); it gives me null, where as I am already logged in

Sinnbeck's avatar

Can you show your Service provider code?

pn523's avatar
Level 2

No, but I am using auth group middleware in route :

Route::middleware(['auth'])->group(function () {
	// My Routes
});
pn523's avatar
Level 2

Sure, here is the code in boot method :

dd(Auth::user());
        $this->registerPolicies();
        Gate::before(function ($user) {
            dd($user);
            if ($user->id == '2') {
                return true;
            }
            else{
                return false;
            }
        });
Sinnbeck's avatar

Ok that should work.. This is my service provider that works

/**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Gate::before(function ($user, $ability) {
            dd($user);
            return $user->hasRole('Admin') ? true : null;
        });
    }
Sinnbeck's avatar

Yes calling Auth::user() in the boot method will return null. That is expected.

pn523's avatar
Level 2

Did not undestand , why Auth::user() will return null ?

pn523's avatar
Level 2

I removed Auth::user(), but it is not printing $user as well, so its not going inside "Gate::before" function.

Sinnbeck's avatar

The user auth isnt handled yet in the boot method, and it therefor return null :)

Can you show the actual route you are trying. Perhaps just paste your web.php content? I cannot reproduce the error.

pn523's avatar
Level 2

Sure, here is the web.php code :

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
Route::get('logout', function(){
    Auth::logout();
    return redirect('/');
});

Route::middleware(['auth'])->group(function () {
    Route::prefix('admin')->group(function () {
        Route::get('dashboard', 'admin\DashboardController@index');
        Route::get('userEdit/{id}', 'admin\UsersController@show');
        Route::get('addRole/{userid}', 'admin\RolesController@add');
        Route::post('saveRole/{userid}', 'admin\RolesController@store');
        Route::get('deleteUserRole/{userid}/{roleid}', 'admin\UsersController@deleteRole');
        Route::put('userUpdate/{id}', 'admin\UsersController@update');
    });
});

Sinnbeck's avatar

And what route are you using? /admin/dashboard? If so, does it show the dashboard?

Sinnbeck's avatar

That should work perfectly! I cannot see any issues. Can you post the DashboardController just for completion?

pn523's avatar
Level 2

Dashboard controller :

<?php

namespace App\Http\Controllers\admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;

class DashboardController extends Controller
{
	public function index(User $user)
	{
	    $data = [
			'pageTitle' => "Dashboard",
			'title' => "Dashboard",
			'users' => $user->all(),
		];
	    return view('layouts.admin.users.roles')->with($data);
	}

	public function edit(User $user)
	{
		$data = [
			'pageTitle' => "Edit User",
			'title' => "Edit User",
			'user' => $user,
		];

		return view('layouts.admin.users.edit')->with($data);
	}
}
Sinnbeck's avatar

Any chance you removed Illuminate\Auth\AuthServiceProvider::class,from the 'providers' array in /config/app.php ? Or changed the 'auth' => \App\Http\Middleware\Authenticate::class,in /app/Http/Kernel.php ?

pn523's avatar
Level 2

These files are untouched, but still I checked and both classes are available

Sinnbeck's avatar

Ok. How about RouteServiceProvider. Any changes to the mapWebRoutes() method?

/**
     * Define the "web" routes for the application.
     *
     * These routes all receive session state, CSRF protection, etc.
     *
     * @return void
     */
    protected function mapWebRoutes()
    {
        Route::middleware('web')
             ->namespace($this->namespace)
             ->group(base_path('routes/web.php'));
    }
pn523's avatar
Level 2

Nope, mapWebRoutes method is exactly same

pn523's avatar
Level 2

UPDATE :

I created fresh project -> setup auth usinglaravel/ui.

But it does not work even in fresh project.

web.php code :


use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
Route::get('hello', function(){
	return "it works";
})->middleware('auth');

AuthServiceProvider code :

<?php

namespace App\Providers;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        // 'App\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();
        Gate::before(function($user){
            dd($user);
        });
        //
    }
}
Sinnbeck's avatar
Sinnbeck
Best Answer
Level 102

It would seem that in the newest version of laravel you need an actual gate to check before it gets triggered

})->middleware('auth', 'can:show,App\User');
1 like
pn523's avatar
Level 2

Although it works I came across an issue, where for a "get" route defined, I was unable to access it because it has the "can:show,App\User", if I remove that middleware it allows to access the route but than I lose the Gate::before functionality

Is there a better way ?

Sinnbeck's avatar

Why would you need the gate before functionality if the route does not have a gate? What are you trying to do with the gate?

pn523's avatar
Level 2

Checking whether user is a superadmin in the gate before and returning true if user is superadmin

Sinnbeck's avatar

But why do you care? If the user is always allowed (no gate) anyways

pn523's avatar
Level 2

Yes removing gate from middleware works, but I did not understand how it worked and than why we implemented "can:show,App\User" (Marked as Best Answer) in the first place, can you please explain the process (Sorry I am new to this) ?

Sinnbeck's avatar

No worries. I will try to explain.

When you want to ensure that some users cannot do a specific action (like open a specific route) you can use a gate to check if the current user is allowed.

This can be checked either using the middleware 'can:action' or inside a controller by using `$this->authorize('action')

They do the same, with the only difference, that the route middleware checks before laravel loads the controller, while the controller method runs after the user gets to the controller.

Now lets say you have a gate called 'delete'. This gate would check if you are indeed the owner of the post you are trying to delete. Using that gate could look a bit like this

$post = Post::find($id);
$this->authorize('delete', $post);

And the gate code

class PostPolicy
{
    /**
     * Determine if the given post can be updated by the user.
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return bool
     */
    public function delete(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }
}

Laravel will call the method and if that check fails, the user will be denied access.

Now back to the Gate::before. With that you can tell it to run a check BEFORE it checks that specific delete gate. If the before check is true, it will never run the delete gate, and just allow you to delete stuff. If the Gate::before returns null (not false!), the check will be forwarded to the delete gate.

So your before check could look like this. Your own user id is 1, meaning you are allowed to do anything

Gate::before(function ($user) {
    if ($user->id == 1) {
        return true;
    }
});
1 like
Next

Please or to participate in this conversation.