PHP Session in Depth

There are a few articles out there that delve bit deeper into the mechanism of php session, like customized session_set_save_handler(), security challenges of php – session fixation etc. But my problem is more about when session file is opened , when session is read ?and when session is saved? in the context of calling session functions like session_start(), or getting and setting of members $_SESSION array, in other words, what really does session_start() do?

I have been the person who knew session in php by just calling session_start() and $_SESSION mentioned here by Chris Shiflet, until one day, I was battling for days to combat an issue of session loss.

I came to this corner by doing a task probably most php developers have done: payment gateway and shopping cart integration, the site I developed has to hand over the flow to payment gateway, then payment gateway call back to my site, as the call back is initiated from another place, how am I going to get back the session after coming back from payment gateway?

Of course there are many ways to handle this situation other than session, like saving the orders to database. But in php, there is a way we can get back session by start session from an known session id, so I chose to stick with session by swapping session_id in the middle of response, this has caused some consequences that for the life of me I could not explain. There might be other causes, but symptom is same: loss of session data, I am sure you can find answers to your session loss from reading this article.

It is all about transaction, in php session retrieving and saving is a process, or within a hidden transaction rather than unit of work, lack of understanding of session transaction will cause unpredictable session results.

Making it more difficult is the lack of official documentation in this respect, here I am going to show you what is happening behind scene by debugging and manually changing session values through session file.

What do I mean by saying session is transactional:

1. Session file is opened(session_start()?)
2. Session file contents read(($_SESSION[] getter is called?)
3. Sessions are used,modified($_SESSION[] setter and getter?)
4. Session file closes, all session values persist(when?)

Myth 1 : what session_start() really does?

Session start will open the session file and read all sessions into $_SESSION, so you can be sure about this by watching $_SESSION variable in debugging, before session_start(), $_SESSION is undefined, after session_start(), the array is created, and session variables loaded.

Myth 2: Is it necessary session_start() called on every request?

Yes, and it must be, reference of $_SESSION does not automatically trigger session_start().

<?php
$_SESSION['B']='b';
echo $_SESSION['B'];

Session [B] is not saved, while no run time error or warning is given.

Myth 3: what happens if session_start() being run more than once

<?php
session_start();

$_SESSION['C']='c';

session_start();

$_SESSION['D']='d';
 

Session[C] and Session[D] will both be saved, and second session_start() will do nothing in terms of session data but give a php Notice like this:

Notice: A session had already been started – ignoring session_start() in C:\ \TestSite\SessionTest\pageg3.php on line 9

It is ignored. While sometime php messages might be silenced, it is good to know that second session_start will not do any good.

So that is why session_start() is always conditional as

if(!isset($_SESSION))
{
  session_start();
}

Myth 4: what if we give it a new session id and session_start()?

<?php
session_start();

$_SESSION['C']='c';

session_id('an23vmh8b2ofk5kt6gdpfmjqlu6');
session_start();

$_SESSION['D']='d';

First you will get the same php Notice as the previous scenario because of the second session_start()

Second, Session[C] ,Session[D] plus original session of user1 are saved into user 2(an23vmh8b2ofk5kt6gdpfmjqlu6) session file, and user1 session is not changed in this case, is this what you want? Can you see the problem here? New session is not allowed to be started according to the notice, but session id is happily replaced.

Solution:
Now it is time I show you how to use session in a way we know what we are going to get.

<?php
session_start();

$_SESSION['C']='c';

session_commit();

session_id('an23vmh8b2ofk5kt6gdpfmjqlu6');
session_start();

$_SESSION['D']='d';

Can you see the difference? Session_commit() is called before another session is started, as I said session handling is transactional, supposedly session_start means the start of transaction, then where is commit of this transaction? In php during a normal request, session transaction is committed after the response stream is closed, But in above example, you need commit the first transaction before you start another one.

Session results in persisted session files are:
for user 1, user 1’s original session+Session[C]
For user 2: user 2’s original session+Session[D], no mess up

Plus there will not be any php Notice for the second session_start()

Myth 5: How does session behave during redirection using header()?

<?php
session_start();
$_SESSION['E']='e';

//redirect
header('Location: page1.php');

There is no need to do session_commit() before header(), as session will be saved and closed before it comes to new page.

This entry was posted on Wednesday, March 30th, 2011 at 3:35 am and is filed under PHP, Software Engineering. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

One Response to “PHP Session in Depth”

Leave a Reply

*