Laravel - Setting auth user inside controller constructor - php

Is it bad practice for me to set the auth user inside my base controller as follows:
abstract class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
protected $user;
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->user = Auth::user();
view()->share('signedIn', Auth::check());
view()->share('user', $this->user);
return $next($request);
});
}
}
Or should I be accessing the auth user inside my controller methods as follows:
public function index()
{
$user = Auth::user();
}
I'm asking based on taylors comments (https://laravel-news.com/controller-construct-session-changes-in-laravel-5-3)
However Jeffery Way seems to be setting this in the constructor as demonstrated in a number of lessons on Laracast?

In newer versions, you can't work with session inside controller constructor as you could in 5.2. You're just watching old lessons.
Also, define middleware in its own class, not in a controller.

Related

Laravel class property not returning in response

I'm creating an API for a blog using Laravel and in my UserController, for some routes, I get the currently authenticated user as seen below:
public function getUser() {
$user = auth()->user();
return response()->json($user, 200);
}
This returns a json object of the user. I get the user in other functions in the same way. I wanted to move this line into a wider scope so I could access it in all functions so I placed it in the constructor:
class UserController extends Controller {
protected $user;
public function __construct() {
$this->user = auth()->user();
}
}
I refactored getUser to look like this;
public function getUser() {
return response()->json($this->user, 200);
}
Now it just returns an empty object and the 200 status code. Why does making it a class property no longer return the object?
The session middleware has not ran yet; the Controller is instantiated before the Request goes through the middleware stack, so you won't have access to session based authentication at that point (so auth()->user() would be null). You can use a Controller middleware to do this though:
class UserController extends Controller
{
protected $user;
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->user = $request->user();
return $next($request);
});
}
}
This middleware will run after the other middleware in the stack so you will have access to the session at that point.

Do Laravel Controllers Share Properties between requests?

Do Laravel controllers share properties between different HTTP requests?
For example if I have the next code
<?php
namespace App\Http\Controllers;
class UserController extends Controller
{
private $user;
public function __construct()
{
$this->user = Auth::user();
}
public function show_user_name() {
return view('user.profile', ['user_name' => $this->user->name]);
}
}
And
Route::get('/user', 'UserController#show_user_name');
Won't it be a mess if several users call /users simultaneously and $user will be the same for all requests?
Your code is incorrect.
You have to use $this-> to set property of class
<?php
namespace App\Http\Controllers;
class UserController extends Controller
{
private $user;
public function __construct()
{
$this->user = Auth::user();
}
...
}
And about your question - No Controllers doesn't share properties between each other. (especially when property is private)
But you can use Auth::user() anywhere you want. It will be same everywhere but will be different for each request because it depends on user cookies, token and session.

Can't access property of extended class with new instance throught ajax Laravel

I will give below code example to better explain:
class BaseController extends Controller
{
public $globalCurrencies;
public $currentCurrency;
public $globalLanguages;
public $currentLanguage;
public function __construct()
{
$this->globalCurrencies = $this->getCurrencies();
$this->globalLanguages = $this->getLanguages();
$this->middleware(function ($request, $next) {
$this->currentCurrency = $this->getCurrentCurrency();
$this->currentLanguage = $this->getCurrentLanguage();
return $next($request);
});
}
CartController
class CartController extends BaseController
{
public function __construct()
{
parent::__construct();
}
BaseController sets up base variables for the app. The cart is using some of them like (current currency). Some of the variables are session based so in base construct there is middleware used to get session data in the constructor). For this part, everything works and cart has access to baseController properties.
Problem occurs here:
class OrderController extends BaseController
{
public function loadPaymentsAndDelivery(Request $request)
{
$cart = new Cart;
dd($cart->globalCurrencies) // WORKS
dd($cart->currentCurrency) // NULL
}
}
Basically, on a new Cart instance, I can access every property created without middleware. Without middleware, I cannot access the session to set up the cart. Method loadPaymentsAndDelivery is loaded via ajax but I tried directly call the method and the properties were still null.
Can somebody explain why this is happening?

Sharing a variable in controller - Laravel

I'm getting the user_id from the session and using it quite a bit throughout my contrpller. So am looking at ways of retrieving that variable.
I have set everything up to get it (How I understand) but the Variable is returning
null
My Controller looks as follows :
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\VideoLog;
class VideoController extends Controller
{
private $user_id;
public function __construct(Request $request)
{
$user_id = session('id');
$this->user_id = $user_id;
}
public function log_watched(Request $request)
{
dd($this->user_id);
// See If Video Has Been Watched Before....
$video_watched = VideoLog::where('user_id', $this->user_id);
}
}
Is it something to do with the session?
How would I retrieve it?
The reason you're having this issue is because the controller __construct method is run before the middleware that starts the session.
(more information here)
As the post says, you can get round this issue by using the middleware method in the controller's __construct method:
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->user_id = session('id');
return $next($request);
});
}
This will allow you to set the user_id on the controller.
Hope this helps!

How to get logged in user in a laravel controller constructor

What I want to do is to get the a User's activation status before running any methods and redirect if they're not active. Here's my code:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
class HomeController extends BaseController
{
public function __construct(){
parent::__CONSTRUCT();
$this->middleware('auth');
//SEE IF ACTIVE, something like auth()->user()->active
}
public function home()
{
return redirect('/home');
}
}
Look at the comment on the last line of the constructor, how do I do that?
From 5.3 onwards, you can't directly access session info in a controllers constructor. You can, though, define a Closure based middleware directly in your controller's constructor. More info in the docs
public function __construct()
{
$this->middleware('auth');
$this->middleware(function ($request, $next) {
if(Auth::user()->active) {
return Redirect::route('activate');
}
return $next($request);
});
}

Categories