In all the sites I’ve developed to date, it’s actually quite rare to find a php bug so although this issue took me a day to fix, I’m actually quite pleased to have found one.
The issue:
Basically, using the php simplexml_load_string() function appears to affect session handling and corrupts the data used in the $_SESSION data causing the error “node no longer exists” error when session_start() is called.
I was using the session system to keep a breadcrumb history for a store I’m developing (retailhealing.com) and had a handful of session varables, each representing a page in the breadcrumb history (crumb1, crumb2, crumb3, … etc).
The code was something like this:
session_start();
...
for ($i=1;$i < 5;$i++) {
$snode='crumb'.$i;
$sdesc='crumbd'.$i;
if (!isset($_SESSION[$snode])) {
$_SESSION[$snode]=0;
$_SESSION[$sdesc]='';
}
}
...
[later in the code, I was also using simple XML]
$parsed_xml = simplexml_load_string($xml);
After the first call to session_start(), when the page was refreshed, I kept getting a ‘node no longer exists’ php error and I couldn’t figure out what was going on.
The solution
A Google search revealed a case similar to mine but the unfortunate poster seems to have been initially flamed by the respondents who rejected it as a bug.
This case was discussing the use of the simplexml_load_string() which I was also using in my code. As a test, I commented out all calls to this function and reloaded my pages. Everything worked just fine.
This pointed the finger of blame directly at the simplexml_load_string() after I of course had spent hours looking at how I was using the $_SESSION[] calls in my code looking for an elusive typo!
So, what was I to do? I could of course just not use simplexml and use a more complex XML parser but I really wanted a quick solution.
The answer was in fact included at the bottom of the case returned in my initial Google search. You need to cast all non string values assigned to session variables to strings as follows:
$_SESSION[variable]=(String)value;
So, my code snippet above now looks something like this:
session_start();
...
for ($i=1;$i < 5;$i++) {
$snode='crumb'.$i;
$sdesc='crumbd'.$i;
if (!isset($_SESSION[$snode])) {
$_SESSION[$snode]=(String)0;
$_SESSION[$sdesc]='';
}
}
This is the first and only time I’ve had to use casting in PHP and I’ve no idea why I need to do it in this case… I’m sure there must be someone out there who can explain?
3 comments ↓
Thanks, this was hugely useful!
I’m unfortunately trying to save whole objects into the session, and I’m having trouble figuring out how to do that without this issue. I’ll let you know if I make any progress.
The problem lies in trying to store objects in the session. In short, you cannot store objects in a session without serializing them first. This effectively switches them in to arrays before they get stored in the session. Them, to get them out, you unserialize them back into objects…
It is a real PITA, but does work in the end …
good luck !
This is excellent information! I had this problem and found your solution, thank you!
Leave a Comment