This month's article is aimed at PHP developers who're not yet familiar with the PHP superglobals. Usage of superglobals is fundamental to PHP web development, but, with all the recent changes in PHP, there are still many outdated tutorials, books, and sadly, still much confusion.


PHP superglobals are automatically available throughout all scripts, in all scopes. In other words, you don't have to do anything, no declaring, no passing - they're just there. They provide useful information about the environment, allow access to HTML form variables or parameters, access to cookies stored on a client, as well as keeping track of sessions and file uploads.


Accessing HTML form variables in PHP

The beginner might still come across an online tutorial or book that has something like the following:


 form.html
<form action='form.php'>
<input type='text' name='email'>
<input type='submit' value='Submit your email'>
</form>

form.php
<?php
print $email;
?>


I strongly suggest reading last month's article, Secure Programming with PHP, in conjunction with this, as that covers some important security issues, and I don't want to be accused of encouraging bad habits. But for now, let's just take these examples at face value, for descriptive purposes. In the above example, $email is a global, and is populated from the form. However, this behaviour causes security issues, and comes from a setting called register_globals. Old versions of PHP had this setting on by default, but newer versions don't, and it's bad practice. $email will not be populated in most PHP installations these days, a cause of much newbie frustration.


So what to do? Simple - PHP creates what are called superglobals that are populated from different places. There are a number that can be used for form data. There's $_GET, $_POST, $_REQUEST and $_GLOBALS. There're also the older variables $HTTP_GET_VARS and $HTTP_POST_VARS. Don't use these any more - they still work, but are deprecated, and don't behave in quite the same way.


$_GET

$_GET is used for data passed using the HTTP GET method, which includes variables passed as part of the URL (such as www.example.co.za/index.php?var1=xx&var2=yy) or from an HTML form that does not define any method (as in the case of form.html above). Here's how a PHP script would access them:


get.php
<?php
// For demonstration only, there are security concerns with doing things this way
echo $_GET['$email']; 
//will display whatever was entered in the form (form.html)
echo $_GET['var1']; 
//will display 'xx' when the script is called from the URL 
//(www.example.co.za/index.php?var1=xx&var2=yy)
echo $_GET['var2']; 
//will display yy from the URL above.
?>
Simple isn't it? The GET method is conventionally used when the processing script has no lasting observable effect on matters (such as changing a database). It's also more easily cacheable, so is ideal most searched.


$_GET has been around since PHP 4.1.0. Before that, $HTTP_GET_VARS was used (though this was not automatically global).


$_POST

The HTTP POST method is very similar, and is conventionally used when the contents of the form are going to change something. But the mechanics are the same, except they use the $_POST superglobal, for example:


postform.html
<form method='POST' action='postform.php'>
<input type='text' name='email'>
<input type='submit' value='Submit your email'>
</form>

postform.php
<?php
print $_POST['email'];
?>


$_POST has been around since PHP 4.1.0. Before that, $HTTP_POST_VARS was used (though this was not automatically global).


$_REQUEST

It's preferable to use the specific superglobal that is intended to contain the variables. If you know a variable is being passed using the GET method, use $_GET. If you know it's being POSTED, use $_POST. But there are times when you may not be sure. I recently came across a script that received the same variable from both the GET and POST methods, depending on how it was called. There's an easy option in this case - use $_REQUEST. It contains all variables passed from both methods, as well as those contained in $_COOKIE (discussed below). In any of the examples above, you could replace $_POST or $_GET with $REQUEST, and the result would be identical.
$_REQUEST has also been around since PHP 4.1.0. Before version 4.3.0, in addition to the contents of $_POST, $_GET and $_COOKIE, $_REQUEST also contained $_FILES (discussed below) information.


$_GLOBALS

The final superglobal that can be used for forms is $_GLOBALS. It's really a super superglobal, as it contains references to all variables in the script's global scope. Replacing $_POST or $_GET with $_GLOBALS in the examples above would also have the identical results. $_GLOBALS has been around since PHP 3.0.0


$_COOKIE

Contains all variables passed from HTTP cookies. $_COOKIE has been around since PHP 4.1.0. Before that, $HTTP_COOKIE_VARS was used (though this was not automatically global).


$_SESSION

This superglobal keeps all session variables. See the article Maintaining State with PHP4 Sessions for more info, or the documentation on PHP sessions.

$_SESSION, as with most of the superglobals, has been around since PHP 4.1.0. Before that, $HTTP_SESSION_VARS was used (though this was not automatically global).

$_SERVER

This superglobal contains information passed from the web server. Web servers differ, so all of the following may not be available under your setup. If you're running PHP from the command line, most of these become pretty meaningless. Here's a list of elements in the array:


It's easy to see what the results would be in your own environment. Create a simple script to loop through and display all elements of the array.


<?
// server.php
foreach ($_SERVER as $key=>$value)
   echo "$key $value<br>" ;
?<


Calling this script with a couple of parameters, i.e. http://phpbuilder.co.za/server.php?var1=2&var2=3, produces the following output:


DOCUMENT_ROOT /var/www/phpbuilder
HTTP_ACCEPT text/xml,application/xml,application/xhtml+xml, text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
HTTP_ACCEPT_CHARSET ISO-8859-1,utf-8;q=0.7,*;q=0.7
HTTP_ACCEPT_ENCODING gzip,deflate
HTTP_ACCEPT_LANGUAGE en-us,en;q=0.5
HTTP_CONNECTION keep-alive
HTTP_COOKIE MANTIS_PROJECT_COOKIE=8; MANTIS_VIEW_ALL_COOKIE=3
HTTP_HOST phpbuilder.co.za
HTTP_USER_AGENT Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.6) Gecko/20050317 Firefox/1.0.6
HTTP_VIA 1.1 cbs-cache1 (NetCache NetApp/5.6.2D16)
HTTP_X_FORWARDED_FOR 165.146.136.106
PATH /bin:/usr/bin:/usr/local/bin
REMOTE_ADDR 198.54.202.18
REMOTE_PORT 23171
SCRIPT_FILENAME /var/www/phpbuilder/server.php
SERVER_ADDR 216.32.75.242
SERVER_ADMIN webmaster@phpbuilder.co.za
SERVER_NAME phpbuilder.co.za
SERVER_PORT 80
SERVER_SIGNATURE
Apache/1.3.33 Server at phpbuilder.co.za Port 80
SERVER_SOFTWARE Apache/1.3.33 (Debian GNU/Linux) PHP/4.3.10-13 mod_ssl/2.8.22 OpenSSL/0.9.7d
GATEWAY_INTERFACE CGI/1.1
SERVER_PROTOCOL HTTP/1.1
REQUEST_METHOD GET
QUERY_STRING var1=2&var2=3
REQUEST_URI /server.php?var1=2&var2=3
SCRIPT_NAME /server.php
PATH_TRANSLATED /var/www/phpbuilder/server.php
PHP_SELF /server.php
argv Array
argc 1


$_SERVER has also been around since PHP 4.1.0. Before that, $HTTP_SERVER_VARS was used (though this was not automatically global).


$_ENV

This varies according to the PHP environment. In my environment, the displaying the entire array by calling the script env.php, below:


<?
// env.php
foreach ($_ENV as $key=>$value)
   echo "$key $value<br>" ;
?<


produces


LANG C
PATH /bin:/usr/bin:/usr/local/bin


$_FILES

When uploading files with an HTTP POST, these elements are populated to provide feedback to the script.


$_FILES has also been around since PHP 4.1.0. Before that, $HTTP_POST_FILES was used (though this was not automatically global).


Conclusion

The PHP superglobals are likely to remain unchanged for a while. After all the recent changes, and resultant confusion for new developers, now's a good time to get it right and learn how to use them properly. Good luck!