After adding proper form to the main layout, like:
...
if(Yii::app()->user->isGuest):
echo CHtml::beginForm(array('site/login'));
...
You may recognize that the user does not get redirected to the previous page correctly.
This is because CWebUser::loginRequired() is not invoked, thus proper states are not saved before the user logs in.
If you want to preserve the referrer you can attach an event handler to your application onEndRequest event with the following content:
$app=Yii::app();
if($app->createUrl($app->user->loginUrl[0])!=$app->request->getUrl())
$app->user->setReturnUrl($app->request->getUrl());
The above code does the following: if the user is at the login page, the referrer is not saved for future reference (otherwise he will be redirected to the login page right after he logged in, which is, of course, not the desired effect).
In any other cases, the previously viewed page is reloaded if the user logs in with the form in the header.
Make sure your login action makes use of this:
$this->redirect(Yii::app()->user->returnUrl);
Your logout process might also use this feature and not send the user back to the front page.
If you are not sure how to attach an event handler to your application object, open up your config file and insert this function at the head of the code (before returning the array):
function endRequest($event)
{
$app=Yii::app();
if($app->createUrl($app->user->loginUrl[0])!=$app->request->getUrl())
$app->user->setReturnUrl($app->request->getUrl());
}
Attaching could be done in your config:
return array(
...
'onEndRequest'=>'endRequest',
...
Bad idea
the problem with this logic is that user will have 'returnUrl' set to whatever last request page url was. That is, for example, url of ANY element on page that might have had 404 error thrown at it. Say, you have a page with 20 images on it, and one image set '404' error off, so after login you'll be redirected to '/images/something_that_isnt_here.jpg' or, more likely, you'll be returned to '/favicon.ico' which is served by "/site/error" (in case it's missing, of course). Peace out!
another way
CController->refresh() /** * Refreshes the current page. * The effect of this method call is the same as user pressing the * refresh button on the browser (without post data). * @param boolean whether to terminate the current application after calling this method * @param string the anchor that should be appended to the redirection URL. * Defaults to empty. Make sure the anchor starts with '#' if you want to specify it. * The parameter has been available since version 1.0.7. **/ public function refresh($terminate=true,$anchor='') { $this->redirect(Yii::app()->getRequest()->getUrl().$anchor,$terminate); }
The 404 problem
This is confusing!
Should Yii::app()->request->getUrl() not return the address/url of the initial page request no matter the HTTP status code? On the other hand, this can easily avoided by adding another condition to check the said status code. However, I doubt it is the right way to do so; but is works for me.
function endRequest($event) { $app = Yii::app(); $error = $app->errorHandler->error; $loginUrl = $app->createUrl($app->user->loginUrl[0]); if( $error->code===200 && $loginUrl != $app->request->getUrl() ) $app->user->setReturnUrl($app->request->getUrl()); }
This is a better approach
function endRequest($event) { $app = Yii::app(); $error = $app->errorHandler->error; $loginUrl = $app->createUrl($app->user->loginUrl[0]); if(!$error instanceof CHttpException && $loginUrl != $app->request->getUrl()) $app->user->setReturnUrl($app->request->getUrl()); }
check if error is not an instanceof CHttpException
@bryglen
!$error instanceof CHttpException
It's much better! Thank you.
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.