I would like to share my little experience with Yii to the community in the form of the below small wiki:
I will demonstrate the user login and logout functionality along with validation errors using aweswome Yiiframework. The blog demo supplied with the standard framework download, provides a simple user login/logout functionality to demonstrate the core framework features. We will add some Ajax functions to this to display login form inside a jQuery modal dialog box with login errors if any. I do make use of ajaxSubmitButton( inside CActiveForm) to add ajax code to the submit button, CJuiDialog for modal dialog box. I will also show you how to separate login action(actionLogin in SiteController) into a separate class file(getLogin) that extends CAction, and later use this class as an action dynamically inside any controller. I use a widget class(loginProvider) and its action(GetLogin) for this purpose. I will now show you what modifications need to be done to the demo application:
- Create a file named loginProvider.php and place it inside the components directory.
<?php
class loginProvider extends CWidget{
public static function actions(){
return array(
'GetLogin'=>'application.components.actions.getLogin',
);
}
public function run(){
$this->renderContent();
}
protected function renderContent(){
echo '<span style="float:right;">';
if(Yii::app()->user->isGuest){
echo CHtml::link('Login', array('/site/login.GetLogin'), array('onclick'=>'$("#login-dialog").dialog("open"); return false;'));
echo '</span>';
$this->getController()->renderPartial('application.components.views.login',array('model'=>new LoginForm));
}
else
echo CHtml::link('Logout ('.Yii::app()->user->name.')', array('site/logout'), array('visible'=>!Yii::app()->user->isGuest));
echo '</span>';
}
}
- Create a directory named actions inside components directory.
- Create the action class with name getLogin.php and place it inside components/actions directory.
<?php
class getLogIn extends CAction{
public function run() {
if (!defined('CRYPT_BLOWFISH')||!CRYPT_BLOWFISH)
throw new CHttpException(500,"This application requires that PHP was compiled with Blowfish support for crypt().");
$model=new LoginForm;
if (Yii::app()->request->isAjaxRequest){
if (isset($_POST['LoginForm'])) {
$model->attributes=$_POST['LoginForm'];
if ($model->validate() && $model->login()){
$array = array("login" => "success");
Yii::app()->user->setFlash("success", "Successfully logged in.");
$json = json_encode($array);
echo $json;
Yii::app()->end();
}
else{
echo CActiveForm::validate($model);
Yii::app()->end();
}
} //POST
}
}
}
- Create a file named login.php and place it inside components/views with the following contents:
<?php $this->beginWidget('zii.widgets.jui.CJuiDialog',array(
'id'=>'login-dialog',
'options'=>array(
'title'=>'Login',
'autoOpen'=>false,
),
));?>
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'user_login_form',
'enableAjaxValidation'=>false,
'enableClientValidation'=>true,
'method' => 'POST',
'clientOptions'=>array(
'validateOnSubmit'=>true,
'validateOnChange'=>true,
'validateOnType'=>false,
),
)); ?>
<h1>
Login</h1>
<p>
Please fill out the following form with your login credentials:</p>
<p class="note">
Fields with <span class="required">*</span> are required.</p>
<div id="login-error-div" class="errorMessage" style="display: none;">
</div>
<div class="row">
<?php echo $form->labelEx($model,'username'); ?>
<?php echo $form->textField($model,'username',array("onfocus"=>"$('#login-error-div').hide();")); ?>
<?php //echo $form->error($model,'username'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'password'); ?>
<?php echo $form->passwordField($model,'password',array("onfocus"=>"$('#login-error-div').hide();")); ?>
<?php //echo $form->error($model,'password'); ?>
<p class="hint">
Hint: You may login with <tt>demo/demo</tt>.
</p>
</div>
<div class="row rememberMe">
<?php echo $form->checkBox($model,'rememberMe'); ?>
<?php echo $form->label($model,'rememberMe'); ?>
<?php echo $form->error($model,'rememberMe'); ?>
</div>
<div class="row submit">
<?php echo CHtml::ajaxSubmitButton(
'Sign In',
array('/site/login.GetLogin'),
array(
'beforeSend' => 'function(){
$("#login").attr("disabled",true);
}',
'complete' => 'function(){
$("#user_login_form").each(function(){ this.reset();});
$("#login").attr("disabled",false);
}',
'success'=>'function(data){
var obj = jQuery.parseJSON(data);
// View login errors!
// alert(data);
if(obj.login == "success"){
$("#user_login_form").html("<h4>
Login Successful! Please Wait...</h4>
");
parent.location.href = "/";
}
else{
$("#login-error-div").show();
$("#login-error-div").html("Login failed! Try again.");$("#login-error-div").append("
");
}
}'
),
array("id"=>"login","class" => "btn btn-primary")
); ?>
</div>
<?php $this->endWidget(); ?>
</div>
<!-- form -->
<?php $this->endWidget('zii.widgets.jui.CJuiDialog'); ?>
- Go to the main layout(blog/protected/views/layouts/main.php) and apply the following changes in the menu:
<div id="mainmenu">
<?php $this->widget('zii.widgets.CMenu',array(
'items'=>array(
array('label'=>'Home', 'url'=>array('post/index')),
array('label'=>'About', 'url'=>array('site/page', 'view'=>'about')),
array('label'=>'Contact', 'url'=>array('site/contact')),
//array('label'=>'Login', 'url'=>array('site/login'), 'visible'=>Yii::app()->user->isGuest),
//array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('site/logout'), 'visible'=>!Yii::app()->user->isGuest)
),
)); ?>
<?php $this->widget('loginProvider'); ?>
</div>
<!-- mainmenu -->
- Finally, Go to SiteController(/blog/protected/controllers/SiteController) and append 'login.' action inside actions() method. Now, the login action is accessed as '/site/login.GetLogin'
<?php
class SiteController extends Controller
{
...
public function actions()
{
return array(
// captcha action renders the CAPTCHA image displayed on the contact page
'captcha'=>array(
'class'=>'CCaptchaAction',
'backColor'=>0xFFFFFF,
),
// page action renders "static" pages stored under 'protected/views/site/pages'
// They can be accessed via: index.php?r=site/page&view=FileName
'page'=>array(
'class'=>'CViewAction',
),
'login.' => array('class'=>'application.components.loginProvider'),
);
}
...
}
- References: (http://www.yiiframework.com/demos/blog/ "Yii Blog") [How to get definite widget in controller] (http://www.yiiframework.com/forum/index.php/topic/18197-how-to-get-definite-widget-in-controller/page__p__89729__hl__widget a action provider #entry89729 "How to get definite widget in controller")
@pravi
Good Work
dialog not opening
For some reason, when i click the login link, the dialog doesn't open
@swampone
Please debug using firebug and find errors if any
login form showing in regular static form once page is loaded
Im still struggling to get this working properly. The login form is showing up on the page once its loaded not inside the dialog box. I have narrowed the issue down to the success callback in the ajaxSubmit button on the login form. Once I remove it, form opens properly in dialog box.
'success'=>'function(data){ var obj = jQuery.parseJSON(data); // View login errors! // alert(data); if(obj.login == "success"){ $("#user_login_form").html("<h4> Login Successful! Please Wait...</h4> "); parent.location.href = "/"; } else{ $("#login-error-div").show(); $("#login-error-div").html("Login failed! Try again.");$("#login-error-div").append(" "); } }
Once i remove the above, it opens in dialog box
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.