tags:

views:

655

answers:

2

I'm trying to create a widget within the module and then load that widget from 'outside' of the module. More particularly I'm using user module written by someone else. I don't want to have a separate page for displaying a login form, therefore I tried to make a CPortlet/widget (confusion) displaying the login form. Basically, I've moved the code from LoginController into that widget. Then I try to display the widget on some random page by

<?php $this->widget('user.components.LoginForm'); ?>

However, I get an error

CWebApplication does not have a method named "encrypting".

in UserIdentity class in this line:

else if(Yii::app()->controller->module->encrypting($this->password)!==$user->password)

This happens, because I'm basically trying to execute this code within context of the app and not the module. Thus the "Yii::app()->controller->module" trick doesn't really work as expected.

  1. What am I doing wrong:-\
  2. Is there a better way to achieve this. I.e. display that login form in some other page, which is normally displayed by accessing login controller within user module (user/login) or is a widget the right way of doing it?

Thanks.

+4  A: 

The quick solution

Ok, so I simply ended up doing

Yii::app()->getModule('user')->encrypting($this->password)

instead of

Yii::app()->controller->module->encrypting($this->password)

Notice that now the module must be called 'user' in the main config, but I think this allows for more flexibility. I.e. we're not bound to only use module functionality within the module.

Additional insight on displaying widget outside of the module scope

After playing more with it that's what I did. In the UserModule.php I've created a method

public static function id() {
    return 'user';
}

Then everywhere where I need the module I use

Yii::app()->getModule(UserModule::id())->encrypting($this->password)

I don't like having many imports related to the module like:

'application.modules.user.models.*',
'application.modules.user.components.*',

Because we already have those imports in the UserModule.php:

public function init()
{
    // this method is called when the module is being created
    // you may place code here to customize the module or the application

    // import the module-level models and components
    $this->setImport(array(
        'user.models.*',
        'user.components.*',
    ));
}

Therefore whenever you know that some piece of functionality will be used outside of the module it's important to make sure the module is loaded. For example, in the LoginForm widget that I am trying to display NOT in one of the module controllers, I have this line of code:

$model = new UserLogin;

However, UserLogin is a model inside of the User module, and in order to be able to autoload this model we first have to make sure the module was initialised:

$module = Yii::app()->getModule(UserModule::id());
$model = new UserLogin;

I hope this will be helpful if you were stuck with the whole modules concept the way I was. http://www.yiiframework.com/forum/index.php?/topic/6449-access-another-modules-model/ was useful but hard to find =)

Karolis
+1  A: 

You better move that encrypting() into a MyUserIdentiy class which extends CUserIdentity. Whatever the code you take to use, they putting the method in controller is a bad idea and as a result you cannot reuse that code.

The login form should still post to User/Login controller but I guess they use Yii's standard login code and you might want to modify it to use the MyUserIdentity.

Pokamy