SOLVED: design for login and persistent user information

Hi all,

I need some help in designing login and persistent user information awareness in the (Yii based) system. By "design" I mean devision to classes and relationship between them, as well as flow of code.

My application relevant characteristics:

The application holds lots of analyzed data for the users, stored in an already existing and designed (and working) database which holds both the user’s login details as well as all their stored data. This data is shown on the site in several ways - in ‘instant information’ little HTML tables on central (dynamic of course) pages. But most importantly, this information is shown in a dashboard area of the site (the dashboard implementation is another story). The information could also influence other parts of the site.

The application should work, as stated, with an already existing and designed database with many related tables. Regarding the database, lets simply assume that the central table is “users” (User Gii generated class) and all other related tables are related to this ‘users’ table and the model classes reflect those relationship.

Preliminary design thoughts

Now, I’m new to Yii (and MVC programming) and was a bit confused on how to achieve this dynamic (per user) and persistent information in Yii. I come from Drupal. There, I had to rape Drupal user management system in several locations in order to both authenticate against my DB and also inject fetched information into the globally available $user variable. The latter is similar in essence, I think, to Yii->app()->user and would love a correction if mistaken here.

In Yii, authenticating against ‘my’ DB is a breeze but I’m not sure how to inject all relevant information of the user into Yii:app()->user. I was recommended by SJFriedl on the IRC channel to do something along the lines of “extend CWebUser and keep a cache of the User model object, such that you’d say Yii::app()->user->userModel and it would only fetch it the first time you asked”.

So much for the long introduction. Now for the questions:

  • How do I bloody model/design this issue? Would you recommend otherwise than the suggested solution?

  • Regarding SJFriedl’s comment, this means to simply at the end of the login process override Yii::app()->user with an object I created, which is an extension of CWebUser, and prior to that assign to this extended CWebUser object a property of my ‘user’ model object?

  • Any other recommendation?

  • Any other enlightenment on the relevant Yii best practices will be appreciated!

TIA,

Boaz.

EDIT: marked as ‘solved’

The suggestion of the extension is a good idea.

For your issue, I would go for this:





protected static $_model;


...


public function getModel(){

   if( null === $this->_model) 

       $this->_model = User::model()->findByPk( $this->id ); // if User is your model class name

   return $this->_model;

}


// now you can access user model

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

     Yii::app()->user->model->attribute



Hope it brings some light…

Cheers

Antonio - thanks for the help.

I’m implementing as suggested. Also useful for me is overriding my CWebUser object property ‘name’ and I guess that the only properties that will need overriding are ‘id’ and ‘name’, as suggested here

See also the very relevant wiki tutorials:

  • This

  • and that

Actually, having quoted them, accompanied by the above text, I think this pretty much solves this,generally speaking (YMMV: according to your requirements and taste)

Hi, how to override afterLogin and beforeLogout function on CWebUser class. I try add code like this but it’s does not work :(.




config/main.php

'user' => array(

    'class' => 'EWebUser',

    'allowAutoLogin'=>true,

);


components/EWebUser.php

class EWebUser extends CWebUser

{

    private $_model;


    public function login(IUserIdentity $identity, $duration=0) {

        parent::login($identity, $duration);

        $this->_model = $identity->getUserModel();

    }


    protected function afterLogin($fromCookie) {

        parent::afterLogin($fromCookie);

        file_put_contents(Yii::getPathOfAlias('webroot').'/after_login.txt', 

            'after login');

        return true;

    }

}



Thanks.

Hi,

sorry, I’ve yet to override those events. For my untrained eyes the code looks ok. Try to debug it by either using a debugger or your favorite method… . Put echo’s and die() just to see what gets called, what’s not, etc. That my advice for now.

Good luck,

Boaz.