Yii-User Login Widget

Hallo !!

I’d like to create a login widget for module Yii-User. I made under module/user/components file called UserLoginWidget.php with code:

<?php

class UserLoginWidget extends CWidget

{

public function init()





{





}





public function run()


{


	Yii::app()-&gt;getModule('user');


	&#036;model=new UserLogin;


	// collect user input data


	if(isset(&#036;_POST['UserLogin']))


	{


		&#036;model-&gt;attributes=&#036;_POST['UserLogin'];


		// validate user input and redirect to previous page if valid


		if(&#036;model-&gt;validate()) {


				//&#036;this-&gt;redirect(Yii::app()-&gt;controller-&gt;module-&gt;returnUrl);


		}


	}


	// display the login form


	&#036;this-&gt;render('userLogin',array('model'=&gt;&#036;model));


   


}

}

I also made view file userLogin.php under module/user/components/view with code:

<div class="span-8">

&lt;div class=&quot;form box&quot;&gt;


&lt;?php echo CHtml::beginForm(); ?&gt;


	&lt;?php echo CHtml::errorSummary(&#036;model); ?&gt;


	


	&lt;div class=&quot;row&quot;&gt;


		&lt;?php echo CHtml::activeLabelEx(&#036;model,'username'); ?&gt;


		&lt;?php echo CHtml::activeTextField(&#036;model,'username', array('size'=&gt;35)) ?&gt;


	&lt;/div&gt;


	&lt;div class=&quot;row&quot;&gt;


		&lt;?php echo CHtml::activeLabelEx(&#036;model,'password'); ?&gt;


		&lt;?php echo CHtml::activePasswordField(&#036;model,'password', array('size'=&gt;35)) ?&gt;


	&lt;/div&gt;


	&lt;div class=&quot;row&quot;&gt;


		&lt;p class=&quot;hint&quot;&gt;


		&lt;?php echo CHtml::link(UserModule::t(&quot;Register&quot;),Yii::app()-&gt;getModule('user')-&gt;registrationUrl); ?&gt; | &lt;?php echo CHtml::link(UserModule::t(&quot;Lost Password?&quot;),Yii::app()-&gt;getModule('user')-&gt;recoveryUrl); ?&gt;


		&lt;/p&gt;


	&lt;/div&gt;


	&lt;div class=&quot;row rememberMe&quot;&gt;


		&lt;?php echo CHtml::activeCheckBox(&#036;model,'rememberMe'); ?&gt;


		&lt;?php echo CHtml::activeLabelEx(&#036;model,'rememberMe'); ?&gt;


	&lt;/div&gt;


	&lt;div class=&quot;row submit&quot;&gt;


		&lt;?php echo CHtml::submitButton(UserModule::t(&quot;Login&quot;)); ?&gt;


	&lt;/div&gt;


&lt;?php echo CHtml::endForm(); ?&gt;


&lt;/div&gt;&#60;&#33;-- form --&#62;

</div>

<?php

$form = new CForm(array(

'elements'=&gt;array(


    'username'=&gt;array(


        'type'=&gt;'text',


        'maxlength'=&gt;32,


    ),


    'password'=&gt;array(


        'type'=&gt;'password',


        'maxlength'=&gt;32,


    ),


    'rememberMe'=&gt;array(


        'type'=&gt;'checkbox',


    )


),





'buttons'=&gt;array(


    'login'=&gt;array(


        'type'=&gt;'submit',


        'label'=&gt;'Login',


    ),


),

), $model);

?>

I’ve just simply copied login code form Yii-User module. I’d like to use this widget on my home page site/index. I placed this code in site/index.php view :

<?php $this->widget(‘user.components.UserLoginWidget’); ?>

Till this moments everything is correct. Login form is correctly displayed, but login funtionality is not working. I keep getting this error:

Fatal error: Call to a member function encrypting() on a non-object in C:\xampp\htdocs\milosnicyzwierzat.pl\protected\modules\user\components\UserIdentity.php on line 35

My UserIdentityForm looks like this:

<?php

/**

  • UserIdentity represents the data needed to identity a user.

  • It contains the authentication method that checks if the provided

  • data can identity the user.

*/

class UserIdentity extends CUserIdentity

{

private &#036;_id;


const ERROR_EMAIL_INVALID=3;


const ERROR_STATUS_NOTACTIV=4;


const ERROR_STATUS_BAN=5;


/**


 * Authenticates a user.


 * The example implementation makes sure if the username and password


 * are both 'demo'.


 * In practical applications, this should be changed to authenticate


 * against some persistent user identity storage (e.g. database).


 * @return boolean whether authentication succeeds.


 */


public function authenticate()


{


	if (strpos(&#036;this-&gt;username,&quot;@&quot;)) {


		&#036;user=User::model()-&gt;notsafe()-&gt;findByAttributes(array('email'=&gt;&#036;this-&gt;username));


	} else {


		&#036;user=User::model()-&gt;notsafe()-&gt;findByAttributes(array('username'=&gt;&#036;this-&gt;username));


	}


	if(&#036;user===null)


		if (strpos(&#036;this-&gt;username,&quot;@&quot;)) {


			&#036;this-&gt;errorCode=self::ERROR_EMAIL_INVALID;


		} else {


			&#036;this-&gt;errorCode=self::ERROR_USERNAME_INVALID;


		}


	else if(Yii::app()-&gt;controller-&gt;module-&gt;encrypting(&#036;this-&gt;password)&#33;==&#036;user-&gt;password)


		&#036;this-&gt;errorCode=self::ERROR_PASSWORD_INVALID;


	else if(&#036;user-&gt;status==0&amp;&amp;Yii::app()-&gt;controller-&gt;module-&gt;loginNotActiv==false)


		&#036;this-&gt;errorCode=self::ERROR_STATUS_NOTACTIV;


	else if(&#036;user-&gt;status==-1)


		&#036;this-&gt;errorCode=self::ERROR_STATUS_BAN;


	else {


		&#036;this-&gt;_id=&#036;user-&gt;id;


		&#036;this-&gt;username=&#036;user-&gt;username;


		&#036;this-&gt;errorCode=self::ERROR_NONE;


	}


	return &#33;&#036;this-&gt;errorCode;


}





/**


* @return integer the ID of the user record


*/


public function getId()


{


	return &#036;this-&gt;_id;


}

}

I belive this is the problem: Yii::app()->controller->module->encrypting, but so far I couldn’t find correct answer. Can anyone help me out?

Regards

LukBB

Could be that Yii::app()->controller->module returns null ?

Check the documentation for this - http://www.yiiframework.com/doc/api/1.1/CController#module-detail

Thanks for reply, I’ve seen it in guide, but don’t know how to use it “It returns null if the controller does not belong to any module” on my home page I use site/index controller, but I need to use LoginController from module User, that’s why I used getModule(‘user’), I tried also to use Yii::import User class but with no luck. I tried to set default controller to login but also didn’t solve the problem

If anyone is interested in login widget for Yii-User module here it is :)

LoginWidget.php under /modules/user/components/

<?php

Yii::import(‘zii.widgets.CPortlet’);

class LoginWidget extends CPortlet

{

public function init()


{


	&#036;this-&gt;title=Yii::t('user', 'Login');


	parent::init();


}





protected function renderContent()


{


	&#036;this-&gt;render('loginWidget', array('model' =&gt; new UserLogin()));


}

}

?>

loginWidget.php view file under /modules/user/components/view/

<?php echo CHtml::beginForm(array(’/user/login’));

$link = ‘//’ .

Yii::app()->controller->uniqueid .

‘/’ . Yii::app()->controller->action->id;

echo CHtml::hiddenField(‘quicklogin’, $link);

?>

&lt;?php echo CHtml::errorSummary(&#036;model); ?&gt;





&lt;div class=&quot;row&quot;&gt;


	&lt;?php echo CHtml::activeLabelEx(&#036;model,'username'); ?&gt;


	&lt;?php echo CHtml::activeTextField(&#036;model,'username', array('size' =&gt; 30)) ?&gt;


&lt;/div&gt;





&lt;div class=&quot;row&quot; style=&quot;padding-top:12px;&quot;&gt;


	&lt;?php echo CHtml::activeLabelEx(&#036;model,'password'); ?&gt;


	&lt;?php echo CHtml::activePasswordField(&#036;model,'password', array('size' =&gt; 30)); ?&gt;


&lt;/div&gt;





&lt;div class=&quot;row submit&quot;&gt;


	&lt;?php echo CHtml::submitButton('Login'); ?&gt;


&lt;/div&gt;

<?php echo CHtml::endForm(); ?>

It is based on YUM login widget

Regards

lukBB

lukBB I wanted to see what you came up with but I can’t get it to function. I get…


include(UserModule.php): failed to open stream: No such file or directory

Do I need to make any other changes to get it working?

Also why did you decide to put the view under components instead of views?

Hi lukBB,

It’s nice of you to share something like this :)

To share your codes clearer, enclose your codes in [code ] and [\code ] tags. (without the space after code) :)

Hi enfield,

I put all this files under modules/user/components, because I wanted to create a widget, small piece of code you could easly use all over your application. To make this work, you should have yii-user module up and running. Link to yii-user Yii-User

To create a login widget put LoginWidget.php under /modules/user/components/


<?php

Yii::import('zii.widgets.CPortlet');


class LoginWidget extends CPortlet

{

	public function init()

	{

		$this->title=Yii::t('user', 'Login');

		parent::init();

	}


	protected function renderContent()

	{

		$this->render('loginWidget', array('model' => new UserLogin()));

	}

} 

?>

and view file loginWidget.php under /modules/user/components/views/


<?php echo CHtml::beginForm(array('/user/login')); 

    

$link = '//' .

Yii::app()->controller->uniqueid .

'/' . Yii::app()->controller->action->id;

echo CHtml::hiddenField('quicklogin', $link);

?>


	<?php echo CHtml::errorSummary($model); ?>

	

	<div class="row">

		<?php echo CHtml::activeLabelEx($model,'username'); ?>

		<?php echo CHtml::activeTextField($model,'username', array('size' => 30)) ?>

	</div>

	

	<div class="row" style="padding-top:12px;">

		<?php echo CHtml::activeLabelEx($model,'password'); ?>

		<?php echo CHtml::activePasswordField($model,'password', array('size' => 30)); ?>

	</div>

	

	<div class="row submit">

		<?php echo CHtml::submitButton('Login'); ?>

	</div>

	

<?php echo CHtml::endForm(); ?>

Now you can simply add this widget to every view file in your application by writing something like this:


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

	{

		$this->widget('application.modules.user.components.LoginWidget'); 

	}

@macinville thank you I was wondering how to do it :)

lukBB, I appreciate the help and you sharing this. I had similar code to yours on my views/site/index.php page and with the latest code you provided or with what I had the same error that I listed before appears.

I have made a number of changes to my yii-user so to make sure it wasn’t my code changes causing the problem I put it on a clean yii-user load and still end up with the same error.

I am new to yii and just learning how to get around so tracking down some of these errors have been difficult for me. Wondering why it works for you and not for me.

I really like the idea of what you have accomplished so I hope to get it working.

This is actually the complete PHP error that is printed out…

The following lines are highlighted


396                 include($className.'.php');


37             'rememberMe'=>UserModule::t("Remember me next time"),


12                 <?php echo CHtml::activeLabelEx($model,'username'); ?>


14                 $this->render('loginWidget', array('model' => new UserLogin()));


include(UserModule.php): failed to open stream: No such file or directory


/Users/../yii/framework/YiiBase.php(396)


384      * @return boolean whether the class has been loaded successfully

385      */

386     public static function autoload($className)

387     {

388         // use include so that the error PHP file may appear

389         if(isset(self::$_coreClasses[$className]))

390             include(YII_PATH.self::$_coreClasses[$className]);

391         else if(isset(self::$classMap[$className]))

392             include(self::$classMap[$className]);

393         else

394         {

395             if(strpos($className,'\\')===false)

396                 include($className.'.php');

397             else  // class name with namespace in PHP 5.3

398             {

399                 $namespace=str_replace('\\','.',ltrim($className,'\\'));

400                 if(($path=self::getPathOfAlias($namespace))!==false)

401                     include($path.'.php');

402                 else

403                     return false;

404             }

405             return class_exists($className,false) || interface_exists($className,false);

406         }

407         return true;

408     }




Stack Trace


#0	

+  /Users/../yii/framework/YiiBase.php(396): YiiBase::autoload()

#1	

 unknown(0): YiiBase::autoload("UserModule")


#2	

–  /Users/../protected/modules/user/models/UserLogin.php(37): spl_autoload_call("UserModule")

32      * Declares attribute labels.

33      */

34     public function attributeLabels()

35     {

36         return array(

37             'rememberMe'=>UserModule::t("Remember me next time"),

38             'username'=>UserModule::t("email"),

39             'password'=>UserModule::t("password"),

40         );

41     }

42 


#3	

+  /Users/../yii/framework/base/CModel.php(330): UserLogin->attributeLabels()

#4	

+  /Users/../yii/framework/web/helpers/CHtml.php(1141): CModel->getAttributeLabel("username")

#5	

+  /Users/../yii/framework/web/helpers/CHtml.php(1167): CHtml::activeLabel(UserLogin, "username", array("required" => true))




#6	

–  /Users/../protected/modules/user/components/views/loginWidget.php(12): CHtml::activeLabelEx(UserLogin, "username")

07 ?>

08 

09         <?php echo CHtml::errorSummary($model); ?>

10         

11         <div class="row">

12                 <?php echo CHtml::activeLabelEx($model,'username'); ?>

13                 <?php echo CHtml::activeTextField($model,'username', array('size' => 30)) ?>

14         </div>

15         

16         <div class="row" style="padding-top:12px;">

17                 <?php echo CHtml::activeLabelEx($model,'password'); ?>




#7	

+  /Users/../yii/framework/web/CBaseController.php(123): require("/Users/../protected/modules/user...")

#8	

+  /Users/../yii/framework/web/CBaseController.php(88): CBaseController->renderInternal("/Users/../protected/modules/user...", array("model" => UserLogin), false)

#9	

+  /Users/../yii/framework/web/widgets/CWidget.php(240): CBaseController->renderFile("/Users/../protected/modules/user...", array("model" => UserLogin), false)




#10	

–  /Users/../protected/modules/user/components/LoginWidget.php(14): CWidget->render("loginWidget", array("model" => UserLogin))

09                 parent::init();

10         }

11 

12         protected function renderContent()

13         {

14                 $this->render('loginWidget', array('model' => new UserLogin()));

15         }

16 } 

17 ?>




#11	

+  /Users/../yii/framework/zii/widgets/CPortlet.php(95): LoginWidget->renderContent()

#12	

+  /Users/../yii/framework/web/CBaseController.php(166): CPortlet->run()

#13	

+  /Users/../protected/views/site/index.php(6): CBaseController->widget("application.modules.user.components.LoginWidget")

#14	

+  /Users/../yii/framework/web/CBaseController.php(119): require("/Users/../protected/views/site/i...")

#15	

+  /Users/../yii/framework/web/CBaseController.php(88): CBaseController->renderInternal("/Users/../protected/views/site/i...", null, true)

#16	

+  /Users/../yii/framework/web/CController.php(866): CBaseController->renderFile("/Users/../protected/views/site/i...", null, true)

#17	

+  /Users/../yii/framework/web/CController.php(779): CController->renderPartial("index", null, true)

#18	

+  /Users/../protected/controllers/SiteController.php(32): CController->render("index")

#19	

+  /Users/../yii/framework/web/actions/CInlineAction.php(50): SiteController->actionIndex()

#20	

+  /Users/../yii/framework/web/CController.php(300): CInlineAction->runWithParams(array("r" => "site/index"))

#21	

+  /Users/../yii/framework/web/CController.php(278): CController->runAction(CInlineAction)

#22	

+  /Users/../yii/framework/web/CController.php(257): CController->runActionWithFilters(CInlineAction, array())

#23	

+  /Users/../yii/framework/web/CWebApplication.php(328): CController->run("index")

#24	

+  /Users/../yii/framework/web/CWebApplication.php(121): CWebApplication->runController("site/index")

#25	

+  /Users/../yii/framework/base/CApplication.php(155): CWebApplication->processRequest()

#26	

+  /Users/../www/index.php(13): CApplication->run()



Hi enfield,

Have you included the Yii-user module in your config.php? The error means it’s not able to include UserModule.php. Probably you have missed this part of Yii-user guide. :)

@lukBB,

You sure know how to say thanks :)

macinville, Yes I have that in there with some additions…to get rid of this error


The table "{{users}}" for active record class "User" cannot be found in the database

Here’s my code


modules'=>array(

        'user' => array(

                   'tableUsers' => 'tbl_users',

                   'tableProfiles' => 'tbl_profiles',

                   'tableProfileFields' => 'tbl_profiles_fields',

Yii User is definitely running and the above code does not appear to affect what lukBB has posted as even when its removed I still get the same error.

Hi enfield,

Hmm…so the module declaration is there…

Right now I can only think of two reasons why you are encountering the said error:

  1. The user folder is not under the modules folder

  2. You are using linux OS and the rights are not set properly so that PHP can access the user folder and its contents.

Btw, did you just encountered the error upon using the UserLoginWidget.php of lukBB? And if you are to use the Yii-User module out of the box, no error is encountered? I maybe barking at the wrong tree. :)

Ok, Just looked into things a bit further. I am on my dev box (native Mac OS build - no stack). As long as the view file is located under


../protected/modules/user/views

then the widget works. I have this problem when trying to use it on my home page


../protected/views/site 

. Do I have to use a path alias or something to recognize views outside of the modules directory? Just fishing here…lack of sleep now and have to get to bed. Will hit it again in the morning. But if you have any ideas I sure do appreciate the help.

hey, Have you added


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

into your import array in main config file? I’ve also added this in main config file under components array


	'user'=>array(

			'class'=>'RWebUser',

			// enable cookie-based authentication

			'allowAutoLogin'=>true,

			'loginUrl' => array('/user/login'),

		),

As far as errors with translation, it can be that in your messages you have ‘Password’ with capital letter, simply comment out all labels and then track down your translation. I think I haven’t had any problems with yii-user module instalation, so probably it’s something easy to solve :)

I have…


'import'=>array(

		'application.models.*',

		'application.components.*',

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

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

	),


'modules'=>array(

		'user' => array(

            'tableUsers' => 'tbl_users',

            'tableProfiles' => 'tbl_profiles',

            'tableProfileFields' => 'tbl_profiles_fields',

        ),


'components'=>array(

		'user'=>array(

			// enable cookie-based authentication

			'allowAutoLogin'=>true,

			'loginUrl' => array('/user/login'),

          ),

I’ll see what I come up with. Like I said I have made a number of changes to my yiiuser but it is running fine and integrating the widget should incorporate without problems. I have tried your widget on a clean yiiuser build also to no avail, same errors. From brief testing it looks like your widget works well (although only in the modules dir for me) and is something that will be a great addition to my project so I really want to get it working. I appreciate you sharing.

So can you use it throughout your site? Even on view files located outside of the modules dir?

Ok lukBB, I am still wondering if you can use this widget on any page outside of the modules dir.

Looks like the problem is coming with this.


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

        {

                $this->widget('application.modules.user.components.LoginWidget'); 

        }

Do you see why this could cause the problem trying to execute it from outside of the modules dir?

I also tried just using this without checking for isGuest but the error still exists


$this->widget('application.modules.user.components.LoginWidget');

hi i’ve just checked i have also this in my import array in main config file


'zii.widgets.*',

. Try this maybe will help. I’m using this widget on my site/index view without any problem, it should work in your app too.

Ok tried adding that and it still is not working. Same error. I wonder if you have something else different too.

I just used yiic and made a fresh yii site install, loaded yii-user and all that works fine. Keeping everything standard with both of those. Added your widget on top and the same error occurs. Checked this in two different environments. One being a native Mac OS dev environment (no stack) and the other running XAMPP on Windows 7.

I hate having to ask since you were kind enough in the first place to share this but if you have 5 min would you mind loading a fresh yii site and new yii-user install and try the same?

I figured if I started with a clean build, ran it on two different environments it would help clear things up as the build I was trying to add it to originally is quite modified from the original yii layout and yii-user code. Unfortunately even on a fresh build it doesn’t work outside of the modules dir.

Anybody else have a chance to try this yet?

Of finally got a working solution. I think, I have not fully tested everything. I added a dedicated path in my php.ini file to UserModule.php

Now I can include your widget throughout my site. I would rather figure out a way to not have to modify my php.ini for this though so tomorrow I will look into working up another solution.

Thanks again for putting all of this together.

hi enfield, I’ve just made fresh yii with yii-user module and all works fine, errors you are facing are connected with translation. Just edit UserLogin.php model from modules/user/models change to


/**

	 * Declares attribute labels.

	 */

	public function attributeLabels()

	{

		return array(

			'rememberMe'=>"Remember me next time",

			'username'=>"username or email",

			'password'=>"password",

		);

	}

it should solve your problem

hi lukBB, I just setup your Widget and it is a great addition to yii-user. Good job and thankyou for sharing here.