Yii 1.1: Add information to Yii::app()->user by extending CWebUser

40 followers

This little tutorial explains a way how you can retrieve more parameters from Yii::app()->user by adding a component that extends CWebUser and retrieves the user information from database table named User.

There is also another method of doing this that retrieves the variables from session or cookie instead:
How to add more information to Yii::app()->user (based on session or cookie)

Steps to follow:
1. Make sure you have got a database User model.
2. Create a component that extends CWebUser.
3. Specify in the config.php what user class the application must use.

1. The User model should be a file like this, that you probably already have, anyway for who doesn't:

<?php
 
// this file must be stored in:
// protected/models/User.php
 
class User extends CActiveRecord
{
    /**
     * Returns the static model of the specified AR class.
     * @return CActiveRecord the static model class
     */
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }
 
    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'User';
    }
}
?>

2. Then we create the WebUser component:

<?php
 
// this file must be stored in:
// protected/components/WebUser.php
 
class WebUser extends CWebUser {
 
  // Store model to not repeat query.
  private $_model;
 
  // Return first name.
  // access it by Yii::app()->user->first_name
  function getFirst_Name(){
    $user = $this->loadUser(Yii::app()->user->id);
    return $user->first_name;
  }
 
  // This is a function that checks the field 'role'
  // in the User model to be equal to 1, that means it's admin
  // access it by Yii::app()->user->isAdmin()
  function isAdmin(){
    $user = $this->loadUser(Yii::app()->user->id);
    return intval($user->role) == 1;
  }
 
  // Load user model.
  protected function loadUser($id=null)
    {
        if($this->_model===null)
        {
            if($id!==null)
                $this->_model=User::model()->findByPk($id);
        }
        return $this->_model;
    }
}
?>

3. The last step, configure the application

// you must edit protected/config/main.php
// and find the application components part
// you should have other components defined there
// just add the user component or if you 
// already have it only add 'class' => 'WebUser',
 
// application components
'components'=>array(
    'user'=>array(
        'class' => 'WebUser',
        ),
),

That's all now you can use the following commands:
Yii::app()->user->first_name - property that returns name
Yii::app()->user->isAdmin() - function that returns admin status
And now you can add all the functions you want to WebUser component.

Total 11 comments

#18114 report it
mem at 2014/09/11 12:57pm
If you have your user details on a different table then the one you store the login details

In your loadModel(), you can use

find()

with a relation between your login details table, and user (ie. student) table, and do something around this:

$this->_model=Student::model()->find("site_user_id = $student_id");

Then you can star retrieving data from your student model as well.

AFAIK, just pay attention to what you wish store on SESSION.

If there's a better way, pls, drop a comment. :)

#16405 report it
anhduc.bkhn at 2014/02/20 03:11am
thanks :)

Thanks :)

#10393 report it
Navarr at 2012/10/25 06:18am
For auto-updating information

If your user has information that you want to auto-update, you can use this:

class WebUser extends CWebUser
{
    private $model = null;
 
    public function getModel()
    {
        if(!isset($this->id)) $this->model = new User;
        if($this->model === null)
            $this->model = User::model()->findByPk($this->id);
        return $this->model;
    }
 
    public function __get($name) {
        try {
            return parent::__get($name);
        } catch (CException $e) {
            $m = $this->getModel();
            if($m->__isset($name))
                return $m->{$name};
            else throw $e;
        }
    }
 
    public function __set($name, $value) {
        try {
            return parent::__set($name, $value);
        } catch (CException $e) {
            $m = $this->getModel();
            $m->{$name} = $value;
        }
    }
 
    public function __call($name, $parameters) {
        try {
            return parent::__call($name, $parameters);  
        } catch (CException $e) {
            $m = $this->getModel();
            return call_user_func_array(array($m,$name), $parameters);
        }
    }
}

which allows you to - well, say you have the attribute "canPost" in your User model - you get to

if(Yii::app()->user->canPost)

The downside, of course, is that it has to run the SQL for pulling a model the first time you Yii::app()->user->[something in the user model] - the upside is that it updates the info from SQL.

#9521 report it
clapas at 2012/08/20 08:23am
Built-in functionality

Why not simply use CWebUser.setState() and CWebUser.getState(). Quoting Yii's Class Reference:

«[setState()] Stores a variable in user session.

This function is designed to be used by CWebUser descendant classes who want to store additional user information in user session. By storing a variable using this function, the variable may be retrieved back later using getState. The variable will be persistent across page requests during a user session.»

#4959 report it
ManInTheBox at 2011/09/01 06:18am
Re: override afterLogin

remove line:

parent::afterLogin($fromCookie);

Add your class in config/main.php like mentioned above.

Note that you should reffer to CWebUser via variable $this instead of Yii::app()->user

That's all

#4226 report it
__agus at 2011/06/17 02:12am
override afterLogin

how to override afterLogin function?. I try to add code like this on EWebUser class but no yet work.

class EWebUser extends CWebUser
{
    protected function afterLogin($fromCookie) {
        parent::afterLogin($fromCookie);
        $fh=fopen(Yii::getPathOfAlias('webroot').'/after_login.txt', 'w');
        fwrite($fh, 'Hello World');
        fclose($fh);
    }
}

Any suggestion?. Thanks

#3822 report it
Russell England at 2011/05/11 11:22am
$user might be null

Great wiki thank you

I just needed to change the isAdmin() function to check if the $user exists, returning 0 if it doesn't

function isAdmin()
{
    $user = $this->loadUser(Yii::app()->user->id);
    if ($user===null)
        return 0;
    else
        return intval($user->role) == 1;
}
#2990 report it
djsistemasweb at 2011/03/05 08:09pm
An alternative using user session

I forgot one line in WebUser.logout:

public function logout($destroySession= true)
    {
        // I always remove the session variable model.
        Yii::app()->getSession()->remove('model');
        parent::logout();
    }
#2989 report it
djsistemasweb at 2011/03/05 07:45pm
An alternative using user session

Hi, I performed this alternative, I expect you like it

class UserIdentity extends CUserIdentity{
 
    private $id;
    private $model;
 
    public function getId()
    {
        return $this->id;
    }
 
    public function getModel()
    {
        return $this->model;
    }
 
 
    public function authenticate()
    {
        $user= User::model()->find('LOWER(email)=?', array(strtolower($this->username)));
 
        if($user === null)
        {
            $this->errorCode= CBaseUserIdentity::ERROR_UNKNOWN_IDENTITY;
        }
        elseif($user->password !== $this->password)
        {
            $this->errorCode= CBaseUserIdentity::ERROR_PASSWORD_INVALID;
        }
        else
        {
            $this->model= $user;
            $this->id= $user->id;
            $this->username= $user->email;
            $this->errorCode= self::ERROR_NONE;
        }
        return !$this->errorCode;
    }
}
class WebUser extends CWebUser{
 
    public function getModel()
    {
        return Yii::app()->getSession()->get('model');
    }
 
    public function login($identity, $duration)
    {
        parent::login($identity, $duration);
        Yii::app()->getSession()->add('model', $identity->getModel());
    }
 
    public function logout($destroySession= true)
    {
        // I always remove the session variable model.
        Yii::app()->getSession()->remove('model');
    }
 
}
#254 report it
viter at 2010/07/27 05:25am
problem with php 5.3 solved

My problem was similar to that described by waveslider. The reason is that Guest is not listed in the user table and therefor it has no id, that is Yii::app()->user->id is not set. In php 5.2 it is ok because it assignes default values to variables but php5.3 does not. So we get error "Trying to get property of non-object" because $user is not created. I solved my problem with code like this:

public function getName()
{
    if(Yii::app()->user->getIsGuest())
    {
      return "";
    }
    else
    {
      $user = $this->loadUser(Yii::app()->user->id);
      return $user->email;
    }
}
#880 report it
khonggiannet at 2010/02/13 06:10am
Get all posts by current user

I found this method is very usefull to get data in Relational Active Record table. For example, each user have many posts. In WebUser declare

function getModel()
{
    $user = $this->loadUser(Yii::app()->user->id);
    return $user;
}

And now to get all posts by the current user, you just call Yii::app()->user->model->posts

Leave a comment

Please to leave your comment.

Write new article
  • Written by: atrandafir
  • Updated by: Yang He
  • Category: Tutorials
  • Yii Version: 1.1
  • Votes: +33
  • Viewed: 98,678 times
  • Created on: Jan 10, 2010
  • Last updated: Jun 30, 2012