I need to have Log in form available for guest users throughout my site on all pages that are exposed to public. I have implemented one solution, but I am concerned is it a good practice to include this kind of logic in main layout file. What I did is that I made a condition to display log in form if user is a guest. Before I started using MVC approach, I would create different main layout files. One would be rendered for guest user, one for admin and so on. But I am not sure what would be the best practice to achieve this separation of content based on permissions. Right now I have only one main layout file, but problem is that it has to be changed dynamically and I am not sure what is the best practice to do that? Here is the part of main.php that isrendering login form:
So first I had to make this [size="3"][font="Arial Black"]if[/font][/size] condition, then load model and form action manually. Is there any better way to do all of this ?
i suggest u use a custom behavior for login required
class RequireLogin extends CBehavior
{
public function attach($owner)
{
$owner->attachEventHandler('onBeginRequest', array($this, 'handleBeginRequest'));
}
public function handleBeginRequest($event)
{
if (Yii::app()->user->isGuest && !preg_match('/login$/', Yii::app()->request->getPathInfo()))
{
Yii::app()->user->loginRequired();
}
}
}
the preg_match defined which page do not use loginRequired(such as /site/login, or file upload)
Yii::app()->user->loginRequired() will redirect to login url when you are not login and after login it will redirect the page u view before
use this you must set CWebUser->loginUrl in /config/main.php or extends CWebUser to override it…
the login form can be named login.php in folder layouts,and don’t forget your login controller
Sorry, but that is not what I need, or I do not understand you.
I said that my login form is in main.php layout file not separate view file.
I have one problem with my current approach. After I try to log in with false credentials, I get error message displayed on login.php file, but actually I need it below my login form. This action is doing login in SiteController
/**
* Displays the login page
*/
public function actionLogin()
{
$model=new LoginForm;
// if it is ajax validation request
if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
// collect user input data
if(isset($_POST['LoginForm']))
{
$model->attributes=$_POST['LoginForm'];
// validate user input and redirect to the previous page if valid
if($model->validate() && $model->login())
$this->redirect(Yii::app()->user->returnUrl);
}
// display the login form
$this->render('login',array('model'=>$model));
}
so it is rendering login view : $this->render(‘login’,array(‘model’=>$model));
I guess that I neet to render referrer page in order to display error messages below login form. But how can I achieve that ? How can I force this action to render referrer page ? So if I try loging in from site/index I need it to render that page, if it is some other page like site/contact then I need it to render contact view.
Okay, I have solved this problem. You just have to create portlet. I am going to post my solution in case that some one else do not know what to do. It is quite simple, but it is doing the job.
You can reuse a lot of the code that you alredy get after creating new yii application using yiic tool. To make and implement this portlet you have to do just 3 steps.
Create the main portlet class. Place it in protected/components directory. I have named mine "LoginFormPortlet.php"
This is the basic code that you need for that file :
<?php
Yii::import('zii.widgets.CPortlet'); // you have to import the CPortlet first
/**
* Portlet that is rendering login form. You can call it anywhere in your view file.
*/
class LoginFormPortlet extends CPortlet
{
/**
* Initializing portlet
*/
public function init()
{
parent::init();
}
/**
* Renders the content of the portlet.
*/
protected function renderContent()
{
$model = new LoginForm; // use LoginForm model that comes after you create new yii app
// if it is ajax validation request
if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
// collect user input data
if(isset($_POST['LoginForm']))
{
$model->attributes=$_POST['LoginForm'];
// validate user input and redirect to the previous page if valid
if($model->validate() && $model->login())
$this->controller->redirect(Yii::app()->user->returnUrl);
}
// display the login form
$this->render('loginForm',array('model'=>$model));
}
}
Create the login form view. In protected/components folder create new folder views. Put your view file in it. I have called mine "loginForm".
This is the basic code that you need for that file ( you can style it however you want ):
<!-- Standard HTML form.
If you want to display error message on the same page where you tried loging in then do not specify the form action! -->
<h4>Log in</h4>
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'login-form',
'enableClientValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
),
));
?>
<div class="row">
<?php echo $form->labelEx($model,'username'); ?>
<?php echo $form->textField($model,'username'); ?>
<?php echo $form->error($model,'username'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'password'); ?>
<?php echo $form->passwordField($model,'password'); ?>
<?php echo $form->error($model,'password'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton('Log in'); ?>
</div>
<?php $this->endWidget(); ?>
</div>
Use your portlet. I have called mine in the main.php layout file, under the sidebar section. You can place yours wherever you want. So in my main.php layout ( in my theme ) I have added this code to call my portlet:
<!-- LOG IN FORM-->
<div id="login">
<?php
if(Yii::app()->user->isGuest)
{
$this->widget('LoginFormPortlet');
}
?>
</div>
<!-- ENDS LOG IN -->