7th November, 2005
PHP Globals 101
Monday, 11:59 am in CodeGirl
This is mostly what I promised ~starfyre [h], but I figured I’d post it here just on the offchance that a random Googler happens to stumble across it.
Anyway, the problems comes from the fact that the latest versions of PHP are trying to introduce ‘safer’ global varaibles. Used to be, back in the day, that you could do things like submit a form with a field called foo and then access the data in that field just by using $foo. Ironically, this was touted as one of the ‘ease-of-use’ features that made PHP so much cooler than, say, CGI-Perl, and so fuckloads of scripts out there do this. Unfortunatley, somewhere along the line the makers of PHP decided this was maybe not such a good idea, and gave admins the option to turn the feature ‘off’; at first it was very uncommon, but as time has worn on it is becoming more and more so. The problem being, that a lot of people (many of them women for whom basic PHP is a very adventurous experience) who used to use custom scripts with ‘unsafe’ globals are now finding their sites don’t work anymore. So what can you do to fix it?
The first step is by understanding exactly what the problem effects; very roughly, it’s any outside data that the server (actually the PHP interpreter) is formatting for use in your scripts. This includes the following:
- Form data (GET and POST);
- Query string data (for those of you who use
?sectionstyle templates); - Cookies and session information; and,
- Server variables (such as
$PHP_SELF).
It does not effect ‘global’ variables that originate from within a script (ie. you make a variable $foo then ‘import’ it into a function via global); these most commonly occur within ‘config’ style include headers, and should remain a-okay.*
To try and make global variables ‘safer’, PHP has introduced something it gives the really user-friendly name of metaglobal arrays. There are several metaglobal arrays (some with overlapping functions!), and what they do is act as containers for data that was previously accessable directly. So in our above form example, to read the data a user has submitted to us in <input name="foo"> – which we used to be able to do with just $foo – we use the metaglobal $_POST array with the key foo; in other words, $_POST['foo'].
It looks longer and messier, and it is, I suppose, but there are also benifits for using metaglobal arrays instead of accessing server variables directly. The first (and most obvious) is that your scripts actually work on sites where the web admin has turned register_globals off. The second is that metaglobals are always global; which cuts down on the global directive. I’m sure there are more, but functionally they’re the two big ones.
Okay, so… where, exactly, has all your data gone? Good question.
$_COOKIE
This metaglobal contains all cookie data. It’s keys are the names of your cookies (as set via setcookie(), so if you set something called mycookie with a value of “hello world!” (using setcookie( 'mycookie', "hello world!" ), you would access the hello world! string via $_COOKIE['mycookie']. $_COOKIE should only be set for user-defined cookies, if for some reason you’re using sessions, then you want $_SESSION.
$_SERVER
This array contains a fixed set of data that is provided for use via the webserver itself. It’s most commonly accessed keys are probably:
-
$_SERVER['PHP_SELF'], which returns the address of the calling script. -
$_SERVER['HTTP_REFERER'], which shows where the current browser has come from (generally used in hit tracking scripts). -
$_SERVER['HTTP_USER_AGENT'], also known as “what browser are you using?”. -
$_SERVER['REMOTE_ADDR']which gives the IP address of the visiting user. -
$_SERVER['REQUEST_URI']which returns what page the current user actually requested. -
$_SERVER['QUERY_STRING']returns everything after the ‘?’ in a URL. This is the all-purpose basic include template script.
$_GET and $_POST
Primarily, these two metaglobal arrays will contain form data. You will most often be working with $_POST, the syntax of which is described above. So, what’s the difference between the two? It’s got to do with HTTP protocols, but basically you can do two things to a webserver; you can get data from it, or you can post data to it. Funtionally, the majority of forms will use the POST action, and thus to access their data you should use the $_POST metaglobal. Realistically, you probably won’t end up using $_GET very much.
$_FILES
Contains data about fields uploaded to a script via one of those ‘Browse…’ form element things. You probably don’t really have to bother about it.
$_REQUEST
This basically contains all of the data already covered seperatley by $_GET, $_POST and $_COOKIE. The obvious question is what’s the point? To which I answer I have no idea, it’s just like that. $_REQUEST is generally found accessing <t>$_GET[/c]’s query string data; so say you have a script test.php?foo=bar&bar=baz, you can access the variables foo and bar (which confusingly contain the strings ‘bar’ and ‘baz’ respectivley) using $_REQUEST['foo'] and $_REQUEST['bar']. Astute readers will also notice that this seems to not only gank $_GET’s functionality but also $_SERVER['QUERY_STRING']. Well, kinda; in the above example, $_SERVER['QUERY_STRING'] would return “foo=bar&bar=baz”. Basically, one parses out the variables neatly and one doesn’t. (Functionally, it’s the difference between mysite.com/?x=page1 and mysite.com/?page1 include templates.)
$_SESSION
Finally, we get to $_SESSION. This metaglobal, a bit like $_COOKIE, stores all data related to a PHP session as set by session_start(). Sessions are a bit too in-depth for this post, but if your script already uses them, note that you can now set session data using direct calls to $_SESSION; for example $_SESSION['ebon'] = "I am so goth!";. This replaces the old session_register() function.
There are a few other arrays, but you’re probably never likely to use them so I’ve left them out for the sake of being lazy. Hopefully now you should have a basic idea of how to fix scripts with broken globals (ie. by replacing the ‘old’ variable names with the new ones). Remember, too, that if you lose a variable, you can usually find it again by sticking a call to phpinfo() somewhere in your script; it will print out the contents of all current metaglobals, and a quick Ctrl + F on your missing data should fins what you’re missing.
I should probably also note that all future code you write should use metaglobal arrays instead of trying to access server data directly. I should note that many of the common scripts used on personal domains (I’m looking at you, CodeGrrl) – asides from being shoddily written in the frist place (again, I’m looking at you) – don’t use metaglobals. Consider yourselves warned… (Though now you should hopefully have the info you need to be able to go through and fix them up yourselves! Yay!)
In completley unrelated news: ~starfyre [h], no, it wasn’t you posting registered-only on the last post that screwed up my reply to your comment. It was me posting my reply as ‘Hidden’; I thought I wrote it so that Hidden posts could be seen by admins, the author and the author of the parent item, but apparently I missed out on that last bit. Anyway, I’ve now set it to Registered, so you should be able to read it… though I think I told you most of what I wanted to say over AIM the other day, so it’s kinda redundant now. Hee.
_________________________________________
* Okay, they should, unless you try and do something fancy with them like registering them against a session. If you know how to do that, you probably don’t need this mini-tutorial anyway.
- Comments By » loadx
- Mood » geeky
- Music » Foo Fighters, "Learn to Fly"
- « Previous
- Next »
Related Posts
Comments
-
Meta global.. no
For the record it’s not ‘meta global’ its SUPER global.
http://www.php.net/manual/en/language.variables.predefined.php#language.variables.superglobalsGoogling meta global won’t give you any real tangible result.
-
Bzzt, Fail!
You know, I would say, “Hrm, interesting…” and be reasonably gracious since I’m 99% certain I triple-checked the PHP manual when I first wrote this back in ‘05…
… but I really know you’re just nitpicking me because of all the times I’ve shown you to be wrong on CodeGrrl, so I think I’m just going to leave it. Have fun with being ‘right’ this time, eh?
-
BZZT, FAIL
Lol, I don’t fall for those sort of traps.
I figured i’d correct you because as i said if you google ‘metaglobal’ you dont really get anything back thats useful however if you google the proper term for it ‘Super global’ you’ll have alot more to work with.As for proving me wrong, I’m yet to see it. Your MySQL discussion was way off and you even admitted yourself to taking it out of context as i was refering to ‘indexes’ not whole tables..low and behold. (which ARE ‘cached’ by default..inside a b-tree)
However if and when you do, then I don’t have the know-all elite attitude and i’ll graciously say “wow, good to know that”.
Until then why don’t you correct this tutorial?
-
Feed Me, Please
Are you… trolling me on my own blog? And you’ve got the – what – lack of self-awareness to try and tell me you don’t have a “know-all elite attitude”? I mean, shit; I know I do, and I’m fine with that (and am articulate enough to back it up), but I also understand big words like ‘irony’ and ‘hypocrisy’.
For the Googlers who are wondering, the thread discussing MySQL is here. I’m not even going to bother trying to rebuff the comment about my supposed “admission” of taking something out of context because, well, it’s not my fault if loadx has trouble reading.
Then again, I see from your blog you’re Christian. So I guess critical thinking’s not really your strong point, huh? Mmm… low blows; how I love you so.
And, while I’m on the subject:
Lol, I don’t fall for those sort of traps.
Really? Because it looks to me like you just did; what with the whole replying to my inflammatory post and all. I know it’s just burning you up inside to reply to this one, too, because I’ve seen you in action and I know – from experience – how desperate you are to prove to everyone that you’re the Big Alpha Geek.
I mean, seriously, this is my own blog. I can do this all day and I love wank.
Bring it on, kid.