Laravel 5: How to add Auth::user()->id through the constructor ? - authentication

I can get the ID of the authenticated user like this:
Auth::user()->id = $id;
Great it works, ... but I have a load of methods which need it and I want a cleaner way of adding it to the class as a whole,so I can just reference the $id in each method. I was thinking of putting it into the constructor, but as Auth::user is a static, I am making a mess of things and don't know how to do it.
Many thanks for your help !

Laravel >= 5.3
you can't access the session or authenticated user in your controller's constructor because the middleware has not run yet.
As an alternative, you may define a Closure based middleware directly in your controller's constructor. Before using this feature, make sure that your application is running Laravel 5.3.4 or above:
class UserController extends Controller {
protected $userId;
public function __construct() {
$this->middleware(function (Request $request, $next) {
if (!\Auth::check()) {
return redirect('/login');
}
$this->userId = \Auth::id(); // you can access user id here
return $next($request);
});
}
}

Instead of using the Facade you can inject the contract for the authentication class and then set the user ID on your controller. Like #rotvulpix showed you could put this on your base controller so that all child controllers have access to the user ID too.
<?php
namespace App\Http\Controllers;
use Illuminate\Contracts\Auth\Guard;
class FooController extends Controller
{
/**
* The authenticated user ID.
*
* #var int
*/
protected $userId;
/**
* Construct the controller.
*
* #param \Illuminate\Contracts\Auth\Guard $auth
* #return void
*/
public function __construct(Guard $auth)
{
$this->userId = $auth->id();
}
}
The guard has an id() method which returns void if no user is logged in, which is a little easier than having to go through user()->id.

You can use Auth::user() in the whole application. It doesn't matter where you are. But, in response to your question, you can use the 'Controller' class present in your controllers folder. Add a constructor there and make the reference to the user ID.
<?php namespace App\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesCommands;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
/* Don't forget to add the reference to Auth */
use Auth;
abstract class Controller extends BaseController {
use DispatchesCommands, ValidatesRequests;
function __construct() {
$this->userID = Auth::user()?Auth::user()->id:null;
}
}
Then, in any method of any controller you can use the $this->userID variable.

Related

Laravel controller based api routing

My normal web app runs w/o any issue. Then I wanted to experiment with APIs. I enabled Passport since I need api authorization (but at this moment, I rather want to get this thing working and I have no idea whether it is a problem with Passport) and I wanted to get simple json output of specific Product. So far, I was not able to get it working. I'll describe contents of each file and if someone can direct me to find the issue in my code, that would be great.
Resources\Product.php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class Product extends JsonResource
{
public function toArray($request)
{
return parent::toArray($request);
}
}
Providers\AuthServiceProviders.php
public function boot()
{
$this->registerPolicies();
Passport::routes();
}
User.php
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
...
}
ProductController.php
class ProductController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function apiShow(Product $product)
{
return new ProductResource($product);
}
...
}
routes/api.php
Route::get('/products/{product}', 'ProductController#apiShow');
Now if I go to http://localhost/public/products/1, it displays the page as expected. But if I type in http://localhost/public/api/products/1, it will always go to home page which is set to localhost/public in HomeController.
If I modify routes/api.php as:
Route::get('/products/{id}', function($id) {
return Product::find($id);
});
I get the correct json output in the browser.

Register an asset in Yii2 for all views in a module?

I have a module in Yii2 containing a lot of controllers, models and views.
How can I register an asset for all views, without register it in all view one by one?
The module has init() method, you can use it for code that needs to be executed every time the module is accessed:
<?php
namespace frontend\modules\users;
use frontend\assets\UsersAsset;
use Yii;
use yii\base\Module as BaseModule;
class Module extends BaseModule
{
/**
* #inheritdoc
*/
public $controllerNamespace = 'frontend\modules\users\controllers';
/**
* #inheritdoc
*/
public function init()
{
UsersAsset::register(Yii::$app->view);
parent::init();
}
}
Don't forget to call parent implementation.

Laravel Read User id in Controller constructor

In my controller(s), instead of fetchingAuth::id() in each method, I've set up an $id property in the controller's class and fetched it once in the constructor. then, in the rest of the methods i'm just refering $this->id, is it considered safe or am I doing something wrong?
Code Sample: http://pastebin.com/pvju54eh
What you could do is inject the Guard instance in your controller and then assign the currently logged in user (if there is one) to a class property:
<?php namespace App\Http\Controllers;
use Illuminate\Contracts\Auth\Guard;
class SomeController extends Controller
{
protected $auth;
protected $user;
public function __construct(Guard $auth)
{
$this->auth = $auth;
$this->user = $this->auth->user();
}
public function someMethod()
{
// Get logged in user’s ID
$userId = $this->user->id;
}
}
I do not see any major problems with this approach even though I have not seen approach used often.
Myself I find it easier to get the $request->user() in controller from Request though.

User scope with Zend Framework

I'm switching a Zend Framework application from mono-user to multi-user.
What is the best approach to include the user scope in the controllers ?
One way would be to add the user id in each methods in every controllers:
/application/controllers/IndexController.php
...
public function indexAction() {
$params['user_id'] = Zend_Auth::getInstance()->getIdentity()->id;
$listHelper->readItems($params);
}
...
An other one would be to create a new User model and fetch his items :
/application/controllers/IndexController.php
...
public function indexAction() {
$userModel = new application_models_user();
$userModel->find(Zend_Auth::getInstance()->getIdentity()->id);
$userModel->readItems();
}
...
I'm wondering what's the best approach that would allow me to write minimal code and if you have another idea to "automagically" add the user scope (db scope, plugin...).
Create an abstract class by extending Zend_Controller_Action
abstract class My_Controller_Action extends Zend_Controller_Action {
private $userModel;
public function getUserModel() {
if(is_null($this->userModel)) $this->userModel = new application_models_user();
return $this->userModel;
}
public function getUserId() {
return $this->getUserModel()->find(Zend_Auth::getInstance()->getIdentity()->id);
}
}
Now use this class as base class for your controllers.

yii - variable available to each controller

I am new to yii.
I am using more than 1 controller in my website and each controller has few actions.
I want to use some variables across each controller (Value of variable will be fixed, I need some constants for a formula). Whats the best place (standard way) to define those variables ?
Should I use session ? (as value is not going to change).
Not sure what you are using your vars for, but you can do it by defining them in your config main.php
'params'=>array(
'someVar1'=>'varValue1',
'someVar2' => 'varValue2',
),
Then you can access them in ANYWHERE by calling
Yii::app()->params['someVar1']
They will be available anywhere in your application.
Or you can extend all your controllers off of a base class and define your constants there
Base Controller:
class Controller extends CController {
const SOME_VAR = 'someValue';
}
Your controller:
class YourController1 extends Controller
{
public function actionIndex()
{
echo parent::SOME_VAR;
}
}
Your other controller:
class YourController2 extends Controller
{
public function actionLogin()
{
echo parent::SOME_VAR;
}
}