laravel middleware within __construct - laravel

I'm using https://github.com/appstract/laravel-multisite which is working fine.
Within my controllers methods, I can var_dump current_site() and the correct information is displayed.
My issue is that within my controller __construct method the current_site function returns null i.e the multi_site object hasn't yet been setup.
public function __construct()
{
//this returns null
var_dump(current_Site());
}
public function index()
{
//this works
var_dump(current_Site());
}
I assuming the constructor is called before the routing has been done and therefore thats the issue, but I wanted to only call the current_site function once and have the controller know which site was being used from the start, so all methods etc would know.
I think this is just a lack of knowledge on my part rather than a code issue...any guidance ?
My route groups as like this
'domain' => 'dealer1.'.config('multisite.host'),
'as' => 'dealer1.',
'middleware' => 'site:dealer1'
I know this is todo with middleware not being done before the __construct being called but should I call it by doing
$this->middleware('CurrentSite');
wWhat step should I do next?
Edit
I've changed my code to
public function __construct()
{
$this->middleware(function ($request, $next) {
//this dumps correctly
var_dump(current_Site() );
$this->currentSite = current_Site();
return $next($request);
});
//this is null
//var_dump($this->currentSite);
//die("here");
}

You could try something like:
public function __construct()
{
$this->middleware(function ($request, $next) {
var_dump(current_Site());
return $next($request);
});
}
https://laravel.com/docs/master/controllers#controller-middleware
Hope this helps!

Related

How to pass data from controller to 'after' middleware in Laravel 6.5

I have the following controller:
class Foo extends Controller
{
public function __construct ()
{
$this->middleware('bar', ['only' => ['store', 'update']]);
}
public function store ()
{
// some code to result $baz object (a model or null)
// pass $baz to Bar middleware for further use
}
}
and the following middleware that should be executed after controller code:
class Bar
{
public function handle($request, Closure $next)
{
$response = $next($request);
// I need to use $baz here
return $response;
}
}
However, I can pass data from a normal middleware to controller using $request->request->add(['baz'=>123]) , but this is not working for 'after' middleware. I think the reason is that $request is not passed by reference in constructor/handle function to be updated for further use, only for consume. I have also tried Session::put() and Session::pull(), but for unclear reasons to me, it won't work (is returning null anytime). To return $baz in Foo.store() method thinking that Bar.handle() method would receive it as result returned, won't work (is returning a Illuminate\Http\RedirectResponse object). I have searched around a lot, but google is returning me only normal(before) middleware case. How can I pass data from Controller to middleware with -after- execution in an elegant way?
I would prefer (if it is possible) a middleware approch for the sake of the question, not an alternative to middleware. Thanks!

How to get current user id in constructor in laravel?

I am using laravel 5.7, but i can't get current user id in __construct().
I also tried Auth:id(), but it also not working.
How to get current user id in constructor?
use Illuminate\Support\Facades\Auth;
class TestController extends Controller
{
public $id;
public function __construct()
{
$this->middleware('auth');
$this->middleware(function ($request, $next) {
$this->id = Auth::user()->id;
return $next($request);
});
dd($this->id);
}
}
Current output is null.
You can only access the session in the closure. Just refactor your code to this:
public function __construct()
{
$this->middleware('auth');
$this->middleware(function ($request, $next) {
$this->id = Auth::user()->id;
dd($this->id);
return $next($request);
});
}
You can now use the value $this->id in your controller methods.
In the example in your question, after you've set the value $this->id, you continue with the request. Since you try to access $this->id outside of the scope of the closure, it still is null in the datadump.
After return you will not go to next statement that's why it is not print.
If you want to use this in view then no need to pass in view you can simply access logged user id like this
{{Auth->user->id}}
if you wan to use this in controller make sure you are logged in.
Sometime session expired then you will not get user id
use Illuminate\Support\Facades\Auth;
class TestController extends Controller
{
public $id;
public function __construct()
{
$this->middleware('auth');
$this->middleware(function ($request, $next) {
$this->id = Auth::user()->id;
dd($this->id);
return $next($request);
});
}
}
The easiest solution is to create a middleware and call it later in the constructor.
php artisan make:middleware FoobarMiddleware
I recommend putting an alias in Kernel.php
protected $routeMiddleware = [
...
'foobar' => \App\Http\Middleware\FoobarMiddleware::class,
]
Constructor:
public function __construct()
{
$this->middleware('auth');
$this->middleware('foobar');
}
I recommend changing the focus of how you are creating everything

Declare a variable to be used in all methods Laravel

What is the best way to declare a variable to be used in all the methods within my controllers and my models:
example .. I want to replace:
Auth::user()
by:
$this->user
What would be the best way to do it?
For Laravel 5.3.4+
Declare the property in your controller and then you can do it like this in its __construct method:
protected $user;
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->user = Auth::user();
return $next($request);
});
}
For versions below, you can just $this->user = Auth::user(); inside __construct.
Reference: https://laravel.com/docs/5.3/upgrade#5.3-session-in-constructors
If you attempt to set a user in your Controller.php's __construct method you will find it won't work.
This won't work:
public function __construct()
{
$this->user = auth()->check() ? auth()->user() : null;
}
This is by design, according Taylor, the framework's creator. He discourages setting your user in the base controller - but, it's up to you how you want to do things. There is a way around this. If you wanted $this->user to be accessible in every controller, you would add this to your Controller.php file:
protected function setUser()
{
$this->user = auth()->check() ? auth()->user() : null;
}
Then in your __construct method call it:
public function __construct()
{
$this->setUser();
}
Now, you can access this->user from any controller method. It will be null if not set, but if you are using Laravel's standard auth guard you shouldn't have much of a problem with unauthenticated users getting through.

Laravel domain group without having to pass domain parameter to controllers

I have all my routes in a domain group but I would like to avoid having the domain as a parameter in each controller method.
So I would like to avoid having this everywhere:
public function show($domain, $id) {}
and would like to just keep it as
public function show($id) {}
I was able to partially make it work with $request->route()->forgetParameter('subdomain') placed in a middleware but it doesn't work in the case of calling redirect()->action('SomeController#show') from a controller method.
Here are some more details:
First, all routes are in a domain group.
Route::middleware(['some_middleware'])->domain('{subdomain}' .website.com)->group(function () {
// .. All routes
} );
Then, in some_middleware I have
public function handle($request, Closure $next) {
// ..
$request->route()->forgetParameter('subdomain');
return $next($request);
}
Then where it doesn't work:
class SomeController {
public function process()
{
// ...
redirect()->action('SimpleController#show', ['simple' => $id]);
}
}
The error I'm getting is:
Missing required parameters for [Route: ] [URI: simples/{simple}].
This only works if I explicitly pass in the subdomain variable.
class SomeController {
public function process()
{
// ...
redirect()->action('SimpleController#show', ['subdomain'=>'some_subdomain', 'simple' => $id]);
}
}
Can anyone suggest a "fix" for this? Thanks in advance :)
With Laravel 5.5+, you can use URL::defaults to set request-wide values for things like the route helper.
https://laravel.com/docs/5.6/urls#default-values
public function handle($request, Closure $next) {
// ..
$subdomain = $request->route('subdomain');
URL::defaults(['subdomain' => $subdomain]);
$request->route()->forgetParameter('subdomain');
return $next($request);
}
You could create a wrapper helper for the action() helper:
if (! function_exists('actionSub')) {
function actionSub($name, $parameters)
{
return action($name, $parameters + ['subdomain' => request()->route('subdomain')]);
}
}
Then use it:
redirect(actionSub('SimpleController#show', ['simple' => $id]));
If someone has a more elegant solution for this, it will be great to see it.

Making global user variable in laravel 5.3

I have this code
Controller.php
public function __construct()
{
$this->user = Auth::user();
view()->share('user', $this->user );
}
HomeController.php
public function __construct()
{
$this->middleware('auth');
parent::__construct();
}
It didn't work so I debug it with debugger and I saw that Auth::user() only return a user after finishing constructing.
i.e in HomeController#index() function
Any idea how to solve it ?
That used to work in laravel 5.2, however in laravel 5.3 you can no longer access session variables or the authenticated user in your controller's constructor. So they provided a work around that looks like this:
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->user = Auth::user();
return $next($request);
});
}
https://laravel.com/docs/5.3/upgrade#5.3-session-in-constructors
You can use auth()->user() or Auth::user() globally without creating any variables. You can use it even in views.
It's an auful idea to dublicate and store whole User object in a variable, session etc.

Resources