This looks like a bug in PHP to me, but it’s been around over many versions, and I might just be missing something. It’s pretty weird. It took me well over an hour to track this down, so I’m writing it up in case it helps someone else.
I’m developing a new site, and want to use URLs like page.php/300 rather than page.php?id=300. It’s slightly more search engine friendly (though these days that’s becoming less and less of an issue), but I also just think it looks cleaner. Especially when you get to the tag view and are using URLs like tag.php/tagname. It just looks better.
So, that’s not a big deal. Pull out everything after the slash in PHP and use that as your ID to grab things from the database. But then I wanted to store the last page the user was on in a session variable, so that other pages can return to the last page automatically. No big deal, I say, easy enough. And I’ve done the exact same thing before on another site without problems.
But it just doesn’t work. It sets the session variable correctly (I can echo it back out and it’s right) and it stays correct through the end of the page (if the last command on the page echos the variable, it’s still right) but the next page the user views has reset the ID after the slash to 0. The session variable could be page.php/42, and then the next page to read the variable reads it as page.php/0.
Where it starts to get weird is that it changes after the page is displayed, before displaying the next page. If I view the session file directly in the /tmp directory (I’m on my development machine at home so this is easy), I can see that the variable has become page.php/0 after viewing the page that sets it correctly. Somehow the variable is right on the last line of the PHP script, and then becomes wrong.
I tried copying $id to another variable and using that, same problem. I tried setting $id by hand rather than getting it from the URL, and then everything worked. Somehow getting it from the URL allowed PHP to change any session variable that was set from it.
The answer?
I had a CSS stylesheet referenced in the header of every page, but since I was still developing the site, I hadn’t actually created that CSS file yet. That was causing the problem. Removing the stylesheet from the header fixed it. Also, creating the stylesheet fixed it.
I still don’t understand why it did that. It feels like a bug, but I’m no PHP expert, so maybe that’s correct.
I tried it out in several different PHP versions (4.1.2, 4.4.1, and 5.0.5) and they all showed the same behavior, which makes me think it might be intentional. It’s certainly not intuitive, and I definitely don’t know what’s going on in the code that makes it happen.
Here’s a sample script to demonstrate the issue:
test.phps (I couldn’t paste the code in here because WordPress kept trying to sanitize it)
Save that as test.php, and make sure you don’t have a global.css file. View the page with a URL like test.php/100 . The first time you should just see “test.php/100″, because the session variable wasn’t set yet. Reload the page, which will show you the old value, re-set the session variable, and then show you the new value. You’ll see “test.php/0″ and then “test.php/100″.
If you remove the “link rel” line that declares the stylesheet, you’ll get “test.php/100″ on both lines, which is what I’d expect to happen. It doesn’t seem right that PHP would go back and change a session variable that was already set.
Any comments? Am I actually doing something wrong, or is this a long-standing bug in PHP?