remember originally submitted form on redirect for required login?

Hi,

I would like to build a site that requires login somewhat like LinkedIn does; e.g. in the process of a page in stead of before accessing a page.

So I’d like any visitor to fill out this form and submit it. When submitted and validated I need to check if the visitor is logged in. If so, the form can be saved to the db. If the visitor is a guest, the login form has to be displayed. After logging in, the data is saved. This is what I’ve got so far:




public function actionCreate()

	{

		$model=new Post;

		if(isset($_POST['Post']))

		{

			$model->attributes=$_POST['Challenge'];

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

			{

				$model->user_id=Yii::app()->user->id;

				if($model->save())

					$this->redirect(array('show','id'=>$model->id));

			}

			else

			{

				Yii::app()->user->loginRequired();

			}

		}

		else

			$this->render('create',array('model'=>$model));

	}



This almost does what I described: anyone can fill and submit the form, it’s saved if the visitor is logged in and a login form is displayed when the visitor isn’t. When the login is successful it correctly returns to this page, but it just shows an empty form again. What I need help on is how to get it to remember the form data when having to log in so it can finish processing the form (e.g. save to the db).

I’m guessing perhaps part of the solution is to move some of this logged-in logic to beforeValidate or afterValidate.

Can someone tell me how to solve this? Thanks!

bump

I’m sorry but I could really use some help on this!

Please clarify what you are trying to do.

You need to pass $_POST[‘Challenge’] data again when they login.

I think I figured it out. I’ll give a short summary below, in case someone else is looking for this here is what I did. Feedback and (security) improvements are also welcome!

I have a form where people can enter a challenge (so this model is called Challenge).

Guests and logged-in users can go to this form and submit it. The form data is saved immediately for users. When guests submit the form this is what happens:

  • the form data ($_POST) is temporarily remembered using the Yii session,

  • the guest is rerouted to the login form,

  • when the guest has successfully logged in, the (now) user is returned to this create action

  • the original form data is retrieved from the session and reloaded (e.g. reassigned to $_POST)

  • the process for staving the data is resumed/finished.

In the /protected/models/ChallengeController.php file:


	/**

	 * Creates a new model.

	 * If creation is successful, the browser will be redirected to the 'show' page.

	 */

	public function actionCreate()

	{

		$model=new Challenge;


		// Reload session in order to restore original pre-login form submission

		// pre-login data should be in $session['guestForm']

		$session=Yii::app()->session;

		$session->open();


		if(isset($_POST['Challenge']) || $session['guestForm']['Model']=='Challenge')

		{

			$model->setScenario('create');

			if (isset($session['guestForm']['Data']))

			{

				$_POST=$session['guestForm']['Data']; // Restore the stored values

				unset($session['guestForm']); // Remove the stored form from the session

			}

			$model->setAttributes($_POST['Challenge']); // set all attributes with post values


			// Check if this was a post preview. if so: validate

			if(isset($_POST['previewPost']))

				$model->validate();

			// If it's not a preview, check if the user is a guest. if not: save the form

			elseif(!Yii::app()->user->isGuest)

			{

				if($model->save())

					$this->redirect(array('show','id'=>$model->id));

			}

			// If the user is guest though, save the form data to the session and reroute to the login form.

			else

			{

				if(isset($_POST['Challenge']))

				{

					$session=new WebSession;

					$session->open();

					$session['guestForm'] = array(

						'Model' => 'Challenge',

						'Data' => $_POST,

					);

				}

				Yii::app()->user->loginRequired();

			}

		}

		else

			unset($session['guestForm']); // Remove any other stored form from the session just to be sure

			$this->render('create',array('model'=>$model));

	}



To use the Yii session for this, I’ve had to add a variable to it. In order to achieve this, I’ve created a component class to extend the built-in Yii session class:

The /protected/components/WebSession.php file:


<?php

class WebSession extends CHttpSession {

	public $guestForm;


	public function init() {

		parent::init();

	}

}

That’s it!

Well done!