Inlcuding Log In Form In Main.php Layout Script

Hello,

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:




		<!-- LOG IN -->

		<?php 

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

		{

		?>

		<div id="login">

		

			<h4>Log in</h4>

			

			<?php $model = new LoginForm; ?>

			

			<div class="form">

			<?php $form=$this->beginWidget('CActiveForm', array(

				'id'=>'login-form',

				'action'=>array('site/login'),

				'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('Login'); ?>

				</div>


			<?php $this->endWidget(); ?>

			</div>

			

		</div>

		

		<?php } ?>

		<!-- ENDS LOG IN -->	



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 ?

Thanks

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

you can see this: http://www.yiiframework.com/extension/yii-user/

for futher understanding

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.

Here is the picture : http://prntscr.com/1afh7q

So I want this error msg "Incoret username or password" to displays below the form not on separate page.

EDIT : I saw now this thread: http://www.yiiframework.com/forum/index.php/topic/9666-login-form-in-layout/

Maybe I will make this portlet that is displaying login form, if I do I will share it with you guys.

oh, u want a login form in every page…

porlet is a better way

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.

  1. 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));

    }


}



  1. 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>




  1. 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 -->



I hope that this post will help you.

Cheers

Thank you trance for sharing this code…