1

In app\Http\Controller there is a master controller class named Controller that all other controllers inherits. In any other controller the following code works fine:

class OtherController extends Controller{

   public function index(){
      dd(\Auth::user()->id);
   }
} 

However, in the Controller.php i.e the parent class, when I try to do something like that in the construct method I have got Trying to get property of non-object error:

class Controller extends BaseController {

    use AuthorizesRequests,
        DispatchesJobs,
        ValidatesRequests;
    public $foo = 'null';

    public function __construct() {
        $this->middleware('auth');
        dd(\Auth::user()->id);//Error is here.
        dd(\Route::getCurrentRoute()->action['controller']);

    }

}

How could I solve this issue?

SaidbakR
  • 13,303
  • 20
  • 101
  • 195

2 Answers2

7

Edit to add an actual answer

Try declaring this method and putting your code in it, before the parent::call_action() line:

public function callAction($method, $parameters)
{
    // Put your code right here

    // then do this last
    return parent::callAction($method, $parameters);
}

Taken from the bottom of this page. The short of it is that callAction is always called right before the destination method is called, but it is also called after the middleware runs, so you will be able to properly access your auth facade. In all likelihood whatever you were trying to do in the constructor will work as you wanted it to in this method.

Original Answer

It's been a bit since I've poked around in laravel 5.4, but if I recall correctly the middleware doesn't fire until after the controller constructor, which means that you specifically can't do what you are trying to do. The auth middleware doesn't populate the Auth facade with the logged in user until after the controller is constructed, but before the controller method is called (which is why your first example works).

I believe that this is the intended behavior, so it is unlikely to change.

The short of it is (unless someone more knowledgeable corrects me) that you will have to find another way to do whatever it is you are trying to do.

Edit to add

Indeed, this question makes it clear that my suspicions were correct. Middleware fires after the controller constructor, which means that you cannot access the logged in user inside the controller constructor. In retrospect this is obviously the case because one thing you can do from within the controller constructor is specify which middlewares the system should run. If the middleware had already run, then you wouldn't be able to do that. So the short of it is that you can't (practically) access the Auth facade from within the controller constructor. This is intentional on the part of the laravel team, so it won't change anytime soon. You will have to find another way to do it.

Community
  • 1
  • 1
Conor Mancone
  • 1,940
  • 16
  • 22
  • Indeed, what I need to achieve is something like `beforeAction` callback in `CakePHP`. i.e before any execution for any controller's action perform specific tasks. – SaidbakR May 18 '17 at 19:43
  • More details on what you are trying to do might help figure out the proper solution – Conor Mancone May 18 '17 at 20:08
  • That's exactly what I need. Indeed I plane to make my own Authorization implementation so using such method in `Controller.php` is essential for this approach. – SaidbakR May 18 '17 at 23:44
2

I have update my answer on the basis of your error... make sure on the top of file add use Illuminate\Support\Facades\Auth;

Now with laravel 4.2+ it is easy to get user's id:

$userId = Auth::id();

that is all.

But to retrieve user's data other than id, you use:

$email = Auth::user()->email;

For more details, check security part of the documentation

Bilal Ahmed
  • 4,005
  • 3
  • 22
  • 42
  • I have got this error: `App\Http\Controllers\Controller cannot use Illuminate\Support\Facades\Auth - it is not a trait` – SaidbakR May 18 '17 at 19:35
  • You don't want to do either of those things. There are two places in PHP where you can put a use directive: at the top of the file (after the namespace but before the class definition) or at the top of the class. A 'use' directive at the top of the class tells PHP you want to use a trait. The auth facade is not a trait, and so (as you discovered) you will get an error if you try to use it as one. If you put a 'use' directive at the top of the file it will basically just alias the class for you in PHP. However, that is not your problem (more in a moment) – Conor Mancone May 18 '17 at 19:56
  • Putting `use Illuminate\Support\Facades\Auth` at the top of the file doesn't actually change anything because your reference to the Auth class is just a shorthand for Illuminate\Support\Facades\Auth. So '\Auth::user()` does the same thing as `use Illuminate\Support\Facades\Auth` followed by `Auth::user()` which is also equivalent to `use Auth` followed by `Auth::user()`. In all cases you are importing the same class, so changing that won't fix anything. – Conor Mancone May 18 '17 at 20:02
  • The example from Laravel 4.2 is not relevant, I'm afraid, because from what I can tell referencing the Auth in the constructor *did* work in earlier versions of laravel. I believe support for that was taken out in laravel 5.3. – Conor Mancone May 18 '17 at 20:02
  • use Auth; on top of the controller – Sid Heart May 18 '17 at 21:34