Unique session data

The problem I’m facing is if I have two tabs/windows open then the session data gets overwritten.

Here is my Enquiry controller action:


public function actionView()

{

	$model=$this->loadModel();

		

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

	{

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

		

		if($model->validate())

		{

			$session=new CHttpSession;

			$session->open();

			

			$session['id']=$model->id;

			$session['supplier_region']=$model->supplier_region;

			$session['supplier_vehicles']=$model->supplier_vehicles;

			$session['commission_value']=$model->commission_value;

				

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

		}

	}

		

	$this->render('view', array(

		'model'=>$model,

	));

}

I then access the session data on actionSend.

Now suppose I have two windows open:

  1. localhost/enquiry/view/id/1

  2. localhost/enquiry/send/id/2

When I submit the form on page ‘view/id/1’ then the page ‘send/id/2’ will now contain new (incorrect) session data. How can I prevent issues like this from occurring?

You can generate a unique id for the session and use it for disambiguation.

Like that:




public function actionView()

{

        $model=$this->loadModel();

                

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

        {

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

                

                if($model->validate())

                {

                        $session=new CHttpSession;

                        $session->open();

                        $sessId= //generate uniqueID (timestamp... autoincrement )

                        $session[$sessId]['id']=$model->id;

                        $session[$sessId]['supplier_region']=$model->supplier_region;

                        $session[$sessId]['supplier_vehicles']=$model->supplier_vehicles;

                        $session[$sessId]['commission_value']=$model->commission_value;

                                

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

                }

        }

                

        $this->render('view', array(

                'model'=>$model,

        ));

}



You can avoid using the session.

You can pass all via $_GET (I know, is not stilish, but what to do… is not possible to redirect a browser with post)

Another soluton is to save in database this data in a separate table, and then redirect using the id of this temporary table (actually is the same of using session, you just save in db)

Hi zaccaria,

Yeah I didn’t really want to use the session but it’s a multi-page form and I had problems in performing validation and switching to different views. In the end the only easy solution was to use sessions!

I will give that solution a try and let you know how it goes!

OK I tried that and I get this error:

Indirect modification of overloaded element of CHttpSession has no effect

for line:

$session[$sessId][‘id’]=$model->id;

Is strange, it looks that in session you can save a variable, not an array.

Try this (is working for me):




if($model->validate())

{


		$session=new CHttpSession;

		$session->open();

		$sessId= 'n'.time();

		$toSave=array();

                $toSave['id']=$model->id;

                $toSave['supplier_region']=$model->supplier_region;

                $toSave['supplier_vehicles']=$model->supplier_vehicles;

                $toSave['commission_value']=$model->commission_value;


		$session[$sessId]=$toSave;

		

		$session->close();

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






Note that the id for the session should start with a letter, not a number.

  1. How come the id should start with a letter? Can we not just use $model->id for $sessid?

  2. How come you are passing ‘sessId’ as GET parameter (in redirect action)?

  3. Is it necessary to use session->close()?

The trick is to use id different for each REQUEST, not for each ID.

If you have 2 windows (or 2 users) that are modifing the same item, their data will collide and one will receive the data of the other.

My idea is to use an id unique among requests, that’s why I use time (but is better to use some counter, I guess).

So:

  1. How come the id should start with a letter? Can we not just use $model->id for $sessid?

I don’t know, if I start with a number it simply doesn’t work

  1. How come you are passing ‘sessId’ as GET parameter (in redirect action)?

That’s because in the next action I need the id for retrive the data form the session

  1. Is it necessary to use session->close()?

I don’t know, in the doc it was written, but I don’t know if it is necessary…