12

I am building an application with multiple user roles and actions. I did follow the official laravel doc (https://laravel.com/docs/5.5/middleware#middleware-parameters).

But in my controller's constructor (from where I call the above middleware) I am using Auth facade to get user details. I know how to use Auth facade, I had implemented it on several places inside my application. But when I use it inside the constructor it returns null (in logged in condition - I double checked that).

I implemented it like this, I have to call two controllers(since only registered users can access that page)

public function __construct()
{
    $role = Auth::user()->role;
    $this->middleware('auth');
    $this->middleware('checkRole:$role');
}

PS: I tried to initialize $role variable as protected and outside the constructor , still not working. Any suggestions will be helpful

Thank you.

HasilT
  • 2,463
  • 2
  • 17
  • 28
  • 2
    I don't understand why laravel did not allow auth inside constructor. – Grald Feb 01 '18 at 12:37
  • @Grald it tends to construct the base at start and run the application on the base, middleware (wich includes auth) is run between base construction and the application run (therefore **middle**ware) – jave.web Feb 17 '19 at 22:09
  • 2
    @Grald in more humanic: First you build a building (by constructors), then you put equipment inside (by middleware) and then you let the public to run inside. So when constructors come, there is no equipment yet, but constructors can say which equipment needs to be installed later. – jave.web Feb 17 '19 at 22:12

4 Answers4

14

That's because constructors are created before middlewares,that's why its returning null.

This answer will propably solve your problems: Can't call Auth::user() on controller's constructor

taavs
  • 659
  • 9
  • 15
7

If you are using the same user table for both "front-end" user and "admin" & want to apply condition in admin controller's constructor.

You can use below.

auth()->user()

And in the constructor you can use below code.

public function __construct(){      
    $this->middleware(function ($request, $next) {      
        if(auth()->user()->hasRole('frontuser')){
            return redirect()->route('home')->withFlashMessage('You are not authorized to access that page.')->withFlashType('warning');
        }
        return $next($request);
    });
}

But I prefer to handle these in separate middleware class instead of writing this in the controllers constructor.

Mahesh Yadav
  • 2,416
  • 20
  • 23
1

In Http/Kernel.php file move this line

    \Illuminate\Session\Middleware\StartSession::class

from $middlewareGroups to $middleware.

Then you can able get Auth in the constructor

0

Laravel already provided a solution for it, which you could find in its official document. https://laravel.com/docs/5.3/upgrade#5.3-session-in-constructors

class UserController extends Controller
{
    public function __construct()
    {
        $this->user_detail;
        $this->middleware(function ($request, $next) {
            $this->user_detail = Auth::user();
            return $next($request);
        });
    }
}
Ketan Chaudhari
  • 329
  • 3
  • 7