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.
Related
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?
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!
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.
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);
});
}
I am new to this concept of DI, and IoC so i might be doing this completely wrong but i am trying to inject the Model that matches a controller into that controllers constructor (UserModel -> UsersController) so that i can mock it later on.
So my model looks like:
use Illuminate\Auth\UserInterface;
class User extends Eloquent implements UserInterface {
public function getAuthIdentifier()
{
return $this->getKey();
}
public function getAuthPassword()
{
return $this->password;
}
}
And i am then trying to inject in UsersController like so :
class UsersController extends Controller {
protected $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function index()
{
//dd( $this->user);
$users = $this->user->all();
foreach ( $users as $user )
print_r($user);
return;
}
}
Then when i hit this controller in the browser i get a "Unresolvable dependency resolving" error.
I noticed that this happend only when the class that i am trying to inject is a sub class of eloquent, if i try the same code with a custom class that do not extend eloquent then it works fine.
Am i missing something?
Further to the comments, I finally got to know that this is a complicated issue. To bypass this you need to bind your model with the IoC and return a new instance of your model manually.
App::bind('User', function()
{
return new User;
});