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);
});
}
Related
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.
How to properly call this middleware closure function in phpunit test so that $user will be set?
Auth::user is mocked and will receive the proper user object, but the function is not called when creating the controller instance.
Here is my code:
use App\Http\Controllers\Controller;
class CustomController extends Controller
{
private $user;
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->user = Auth::user();
return $next($request);
});
}
}
Phpunit:
use Illuminate\Foundation\Testing\TestCase;
use Illuminate\Support\Facades\Auth;
use App\Models\User;
use App\Controllers\CustomController;
class CustomControllerTest extends TestCase
{
use CreatesApplication;
private $customController;
public function setUp()
{
Auth::shouldReceive('user')->andReturn(new User());
$this->customController = $this->app->make(CustomController::class);
}
}
You are resolving the controller out of the container, but then you aren't passing it any requests to handle. Your middleware code will only be executed when the controller is given something to handle.
As such, $this->middleware(...) simply says "execute this middleware when a request is sent through the pipeline".
Simply test a standard request hitting your endpoint, and then assert what you need to assert.
$this->get('your_endpoint');
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.
First of all, I already check that in other controller (not in resource controller) my session work very well, but when I did it in the resource controller my code for get session didn't work.
Here's my resource controller
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
//tambahan
use DB;
use Session;
//model
use App\_admins;
use App\Mahasiswas;
class MahasiswaController extends Controller
{
protected $data;
protected $token;
public function __contruct(){
$this->data = array();
$this->middleware(function ($request, $next) {
$this->token = $request->session()->get('_admin_id');
if (!$request->session()->has('_admin_id')) {
abort(404);
}
return $next($request);
});
}
private function user($token){
$this->data['query'] = _admins::find($token);
}
public function index(){
echo $this->token;
}
There is more public function, but it's still empty so I am not showing it here to avoid confusion. And here is my route in web.php:
Route::group(['namespace' => 'Admin'],function(){
Route::resource('/admin/mahasiswa','MahasiswaController');
Route::resource('/admin/nilai','NilaiController');
});
In 5.3 the middleware hasn't run yet in the constructor, so you're unable to gather session data. But using your closure-based approach, you should be able to access it with something like this:
$this->middleware(function($request, $next) {
// Get the session value (uses global helper)
$this->token = session('_admin_id');
// If the value is null, abort the request
if (null === $this->token) abort(404);
return $next($request);
});
I have added a controller for my package and I need to call Auth methods inside the constructor of this controller but I get the following error :
ReflectionException in Container.php line 734:
Class hash does not exist
Here is my code :
use Auth;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Session;
class CartController extends Controller
{
private $customer;
public function __construct()
{
$this->middleware('auth', ['except' => ['add']]);
$multiauth = config('cart.multiauth');
if ($multiauth) {
$guard = config('auth.defaults.guard');
$this->customer = Auth::guard($guard)->user();
} else {
$this->customer = Auth::user();
}
}
public function add()
{
// Code
}
}
When I add the code of constructor inside the other functions it works properly but it fails when it is called from constructor of the controller.
I have searched alot for this and found no working solution.
I've solved the problem by adding a middleware :
namespace myNamespace\myPackage;
use Closure;
use Illuminate\Support\Facades\Auth;
class CustomerMiddleware
{
public function handle($request, Closure $next)
{
$multiauth = config('cart.multiauth');
if ($multiauth) {
$guard = config('auth.defaults.guard');
$customer = Auth::guard($guard)->user();
} else {
$customer = Auth::user();
}
$request->attributes->add(['customer' => $customer]);
return $next($request);
}
}
Then I used this middleware for the 'cart/add' route :
Route::group(['middleware' => ['web']], function () {
Route::group(['middleware' => 'customer'], function() {
Route::post('cart/add',
'myNamespace\myPackage\CartController#add');
});
});
So by checking the $request->get('customer') parameter inside the 'add' method of 'CartController', I have access to information of current user :
class CartController extends Controller
{
public function __construct() { }
public function add()
{
$customer = $request->get('customer');
// Code
}
}
I hope this helps someone else :)
You can't use middleware in controller __construct , create a functions and use it