returnUrl is index.php

I have a login link on the top of all pages - this points to mysite/member/login

Sometimes when I click this link and submit the login form, it redirects me back to mysite/index.php

So I echo’d Yii::app()->user->returnUrl; and it is actually being set to mysite/index.php

I haven’t modified the login function in the controller - it is just the same default code.

This only happens when I directly access the login page - if the login page is displayed due to a redirect (if the requested page requires authentication) then it works as expected.

Basically what I want is if the login page is accessed directly, then it should redirect to the member panel - mysite/member.

I won’t be much help here, but are you 100% sure that something in your code is not nulling (emptying) your returnUrl, if you are accessing login form directly?

I have exactly the same situation - a login link (or logout, if user get logged in) on every page as long as redirection that when accessing any page as a guest, user must me redirected to a login page. It is whole build upon default application login/logut code and is working like a charm - no matter if I use login link or access login form directly I’m always redirected to previously seen page.

EDIT: But wait… How can you access your login form directly?

Yes it’s redirecting back to the previous page - this bit is working fine - however what I want is if the user navigates directly to ‘mysite/member/login’ then upon successful login it should not redirect back to previous page, but to ‘mysite/member/index’.

If the user lands on page ‘mysite/member/login’ due to redirect then it should return to the previous URL as per normal.

If I’m not mistaken, If you are accessing login page directly, you are landing back to your index.php page after login because, your returnUrl is empty in this case (there is no server referrer as you accessed login page directly). Therefore, only check if returnUrl is empty, and then redirect where you want, assuming that this is empty, because of direct login form access.

In original code:


//Validate user input and redirect to the previous page if valid

if($model->validate() && $model->login()) $this->redirect(app()->user->returnUrl);

change to something like that:


if($model->validate() && $model->login()) $this->redirect((app()->user->returnUrl == '') ? 'mysite/member/index' : app()->user->returnUrl);

But I must be missing something, because it can’t be that obvious - I think you are looking for something else.

Hi, no returnUrl is not empty, it just defaults to ‘mysite/index.php’.

I know I can put in that conditional statement but I want something more clever.

Considering I have ‘showScriptName’ set to false, I’m not sure why index.php is being included.

Basically this is what I want:

  • If I directly access ‘mysite/member/login’ then it should redirect to ‘mysite/member/index’ upon successful login. At the moment it is redirecting to ‘mysite/index.php’.

  • If for example I access ‘mysite/member/details’ - then this page needs authentication so it will bring up ‘mysite/member/login’. Now upon successful login it should redirect back to ‘mysite/member/details’.

I found another problem with returnUrl:

If I am not logged in and I go to URL ‘mysite/member/user/update’, the login page is displayed and the returnUrl is set to ‘mysite/member/user/update’.

Now suppose I decide not to log in and instead I go back to the home page, or the contact page. I then click on the ‘Login’ link (‘mysite/member/login’) and the returnUrl is still set to ‘mysite/member/user/update’.

This means if I now log in, it will take me that URL.




$this->redirect(($referrer = Yii::app()->getRequest()->getUrlReferrer()) !== null ? $referrer : Yii::app()->getUser()->getReturnUrl());



Hi jayRulez,

That is not the correct answer I’m afraid.

When I say directly access the login page, this means either by entering the URL directly in to the address bar, or clicking on the ‘Login’ link at the top of the page.

In both of these situations, returnUrl is always mysite/index.php. In addition there is the issue I specified in my previous post.

Have you tried the code or are you just saying it isn’t correct? Reason why I asked this is because it does exactly what you described that you wish to happen.

Of course I’ve tried it, like I said it’s not the correct answer, and furthermore it does not work for situations where the login page is not accessed directly.

The issue is with the setting of returnUrl - if this can get set correctly then no need to change the redirect action.

Have you tried replicating my problem?

Yii does not do what you want to do out of the box so you may have to override CWebUser::getReturnUrl(), CWebUser::loginRequired(), and maybe CWebUser::before/afterLogin() to accomplish this depending on how genious you want to be. It’s quite easy really.

Any body can explain me that how could i rid off from this problem…!!

It happens because accessing to returnUrl calls getReturnUrl() method:


        public function getReturnUrl($defaultUrl=null)

        {

                return $this->getState('__returnUrl', $defaultUrl===null ? Yii::app()->getRequest()->getScriptUrl() : CHtml::normalizeUrl($defaultUrl));

        }

And actually you never get null from this. When Yii::app()->user->returnUrl is not set, it returns Yii::app()->getRequest()->getScriptUrl() (.../index.php).

I think, the best way to solve all above problems is to control returnUrl ;) I suggest to make 2 fixes:

your Controller - by default protected/components/Controller.php (add this method)


        public function run($actionID)

	{

		$route = '/'.$this->getUniqueId().'/'.$actionID;

		if($route != Yii::app()->user->loginUrl[0])

		{

			Yii::app()->user->setReturnUrl(null);

		}

		parent::run($actionID);

	}

It clears the returnUrl state (session variable) when you leave login page.

your actionLogin() (add some code to this action)


        public function actionLogin()

	{		

		$returnUrl = Yii::app()->user->getState('__returnUrl');

		$referrer = str_replace(Yii::app()->request->getHostInfo(), "", Yii::app()->request->getUrlReferrer());

		if($referrer!=null && $referrer!=Yii::app()->request->getUrl() && empty($returnUrl))

		{

			Yii::app()->user->setReturnUrl($referrer);

		}

		else if($referrer!=Yii::app()->request->getUrl() && empty($returnUrl))

		{

			$url = Yii::app()->homeUrl;

			if(is_array($url))

			{

				$route=isset($url[0]) ? $url[0] : '';

				$url=$this->createUrl($route,array_splice($url,1));

			}

			Yii::app()->user->setReturnUrl($url);

		}

			

		$model=new LoginForm();


...


			if($model->validate() && $model->login())

			{

				$this->redirect(Yii::app()->user->returnUrl);

			}


...


}

If returnUrl has been already set, then it will redirect you to that page. Otherwise if the referrer URL is not the login page, it will redirect to that URL. What if there is no returnUrl nor refferer? It sets homeUrl as returnUrl ;)

Encountered this issue as well. It is funny that you can actually set returnUrl in the config, but it gets lost somewhere out there…

I find this working nice:




class WebUser extends CWebUser

{

	/**

	 * @var mixed default route to use for returnUrl. Defaults to null.

	 * Accessed if $defaultUrl in getReturnUrl($defaultUrl) is null.

	 */

	public $defaultReturnUrl;

	public function getReturnUrl($defaultUrl=null)

	{

		if($defaultUrl===null) 

			$defaultUrl=$this->defaultReturnUrl;

		return parent::getReturnUrl($defaultUrl);

	}

}



config:


	'components'=>array(

		'user'=>array(

			'class'=>'WebUser',

			'defaultReturnUrl'=>array('site/index'),

		),

		....



Of course you could just hard-code the defaul $defaultUrl value to something else than null but I love quick access to config.

In any case this should be default functionality, IMHO.

I reported the "bug" here: http://code.google.com/p/yii/issues/detail?id=2778

And it was marked as invalid, with the following response:

This is not an issue. Unless you call loginRequired(), you would have to explicitly set returnUrl to remember the current URL.

How do I use loginRequired() to accomplish the task?

I spent way too much time on this, but this is how I solved it. Using your code as the example:




class WebUser extends CWebUser

{

    public $returnUrl = array("mysite/member/index");

   

    /**

     * Initializes the application component.

     * This changes the order of the redirection so that the user session state 

     * takes precedence.

     */

    public function init()

    {

        parent::init();

		

        // set redirecting url as highest priority

        $returnUrlFromState = $this->getState("__returnUrl");

        if ($returnUrlFromState)

        {

            $this->returnUrl = $returnUrlFromState;

        }

    }

}

   



Thanks Jay, that did the trick for m! All I wanted was to be able to call an action that would set a viewmode setting and then return to the same page. I had it all working except the return part and plugged in your code and it worked.

I know this topic is quite old now but thought I would add this as Qiang did actually come back to the reported error with a solution.

The solution is to use:

Yii::app()->user->getReturnUrl($yourUrl)

Where $yourUrl is whatever you want to default to if no returnUrl is set. In my case this was the user profile page so if you login directly, you get your profile. If you login as a result of auth requirements on a page, you get that page after login.

You can go previous page using this also…

<?php CHtml::button(‘Back’,array(‘onClick’=>‘history.go(-1)’)) ?> ::)