search for in the  
<VariablesVariable scope>
Last updated: Thu, 19 May 2005

Predefined variables

PHP provides a large number of predefined variables to any script which it runs. Many of these variables, however, cannot be fully documented as they are dependent upon which server is running, the version and setup of the server, and other factors. Some of these variables will not be available when PHP is run on the command line. For a listing of these variables, please see the section on Reserved Predefined Variables.

Warning

In PHP 4.2.0 and later, the default value for the PHP directive register_globals is off. This is a major change in PHP. Having register_globals off affects the set of predefined variables available in the global scope. For example, to get DOCUMENT_ROOT you'll use $_SERVER['DOCUMENT_ROOT'] instead of $DOCUMENT_ROOT, or $_GET['id'] from the URL http://www.example.com/test.php?id=3 instead of $id, or $_ENV['HOME'] instead of $HOME.

For related information on this change, read the configuration entry for register_globals, the security chapter on Using Register Globals , as well as the PHP 4.1.0 and 4.2.0 Release Announcements.

Using the available PHP Reserved Predefined Variables, like the superglobal arrays, is preferred.

From version 4.1.0 onward, PHP provides an additional set of predefined arrays containing variables from the web server (if applicable), the environment, and user input. These new arrays are rather special in that they are automatically global--i.e., automatically available in every scope. For this reason, they are often known as 'autoglobals' or 'superglobals'. (There is no mechanism in PHP for user-defined superglobals.) The superglobals are listed below; however, for a listing of their contents and further discussion on PHP predefined variables and their natures, please see the section Reserved Predefined Variables. Also, you'll notice how the older predefined variables ($HTTP_*_VARS) still exist. As of PHP 5.0.0, the long PHP predefined variable arrays may be disabled with the register_long_arrays directive.

Variable variables: Superglobals cannot be used as variable variables inside functions or class methods.

Note: Even though both the superglobal and HTTP_*_VARS can exist at the same time; they are not identical, so modifying one will not change the other.

If certain variables in variables_order are not set, their appropriate PHP predefined arrays are also left empty.

PHP Superglobals

$GLOBALS

Contains a reference to every variable which is currently available within the global scope of the script. The keys of this array are the names of the global variables. $GLOBALS has existed since PHP 3.

$_SERVER

Variables set by the web server or otherwise directly related to the execution environment of the current script. Analogous to the old $HTTP_SERVER_VARS array (which is still available, but deprecated).

$_GET

Variables provided to the script via URL query string. Analogous to the old $HTTP_GET_VARS array (which is still available, but deprecated).

$_POST

Variables provided to the script via HTTP POST. Analogous to the old $HTTP_POST_VARS array (which is still available, but deprecated).

$_COOKIE

Variables provided to the script via HTTP cookies. Analogous to the old $HTTP_COOKIE_VARS array (which is still available, but deprecated).

$_FILES

Variables provided to the script via HTTP post file uploads. Analogous to the old $HTTP_POST_FILES array (which is still available, but deprecated). See POST method uploads for more information.

$_ENV

Variables provided to the script via the environment. Analogous to the old $HTTP_ENV_VARS array (which is still available, but deprecated).

$_REQUEST

Variables provided to the script via the GET, POST, and COOKIE input mechanisms, and which therefore cannot be trusted. The presence and order of variable inclusion in this array is defined according to the PHP variables_order configuration directive. This array has no direct analogue in versions of PHP prior to 4.1.0. See also import_request_variables().

Caution

Since PHP 4.3.0, FILE information from $_FILES does not exist in $_REQUEST.

Note: When running on the command line , this will not include the argv and argc entries; these are present in the $_SERVER array.

$_SESSION

Variables which are currently registered to a script's session. Analogous to the old $HTTP_SESSION_VARS array (which is still available, but deprecated). See the Session handling functions section for more information.



User Contributed Notes
Predefined variables
dompody [at] gmail [dot] com
15-May-2005 08:08
To urbanheroes:

version_compare() is only in PHP version 4.1.0 and up. This completely negates your function, since if the version is less than 4.1.0 it will generate an error anyway. The better solution is to do what is stated in the post above yours:

<?php
if (!isset($_SERVER))
{
  
$_GET    = &$HTTP_GET_VARS;
  
$_POST    = &$HTTP_POST_VARS;
  
$_ENV    = &$HTTP_ENV_VARS;
  
$_SERVER  = &$HTTP_SERVER_VARS;
  
$_COOKIE  = &$HTTP_COOKIE_VARS;
  
$_REQUEST = array_merge($_GET, $_POST, $_COOKIE);
}
?>

Include that before everything else in your script and it will fix the flaw.
myfirstname dot barros at gmail dot com
27-Apr-2005 10:10
vars in $_REQUEST are *not* a reference to the respective $_POST and $_GET and $_COOKIE ones.

Consider:
http://site.com/index.php?avar=abc

index.php:
<?php
$_GET
['avar'] = 'b';
print_r($_GET); print('<br>');
print_r($_REQUEST);
?>

output:
Array ( [avar] => 'b' )
Array ( [avar] => 'abc' )
sendoshin[at]noodleroni[dot]com
26-Apr-2005 08:58
There is one way to safely execute PHP code files without running the risk of compromising your own code.  A prior note pointed out that the code being evaluated would still have access to globals using the global keyword.  While this is a valid point, there's one other approach to be looked at - one which actually gives you much more ability than just unsetting some variable references.  It's known as code parsing.

The specifics would be different and much more complex in a deployed site, but here's an extremely strip-down example of how to restrict access to global variables:

<?php
  
while ($x = stristr ($code_to_eval, "global")) {
      
$temp = substr ($code_to_eval, 1, $x-1);
      
$temp .= substr ($code_to_eval, stristr ($code_to_eval, ";", $x) + 1);
      
$code_to_eval = $temp;
   }
  
$ret_val = eval ($code_to_eval);
?>

Of course, that's just a rudimentary example, and a deployment version would have much more checking involved, but parsing the file before you eval it lets you remove any code you don't want to let run, thus making it as safe as your parsing rules.
lanny at freemail dot hu
10-Apr-2005 05:32
From PHP 5.0.3 long predefined arrays such HTTP_GET_VARS got disabled by default. For backward compatibility you can enable them in php.ini:

register_long_arrays = On

I sugget a big WARNING up there like that one with the resister_globals.

Anyway.. I cannot understand why they do such tings all the time.
16-Feb-2005 07:35
php.net uses this

// Backward compatible array creation. After this point, the
// PHP 4.1.0+ arrays can be used to access variables coming
// from outside PHP. But it should be noted that these variables
// are not necessarily superglobals, so they need to be global-ed!
if (!isset($_SERVER))
{
   $_GET    = &$HTTP_GET_VARS;
   $_POST    = &$HTTP_POST_VARS;
   $_ENV    = &$HTTP_ENV_VARS;
   $_SERVER  = &$HTTP_SERVER_VARS;
   $_COOKIE  = &$HTTP_COOKIE_VARS;
   $_REQUEST = array_merge($_GET, $_POST, $_COOKIE);
}

$PHP_SELF = $_SERVER['PHP_SELF'];
kasey at cornerspeed dowt com
14-Jun-2004 08:33
I have a few points to note to (debabratak at softhome dot net).  Firstly, extracting all your variables from the global variable arrays is rather cumbersome and possibly unsafe.  This causes longer run times, and wastes more memory.  Then, your script is starting the session before it parses the superglobals.  Bad things can happen because of this:

<?php

// user sent a GET header with key = secret_access, val = true, so

echo $_GET["secret_access"]; // output: true
echo $secret_access; // output:

session_start();

// in previous logic, you set session variable $secret_access = false

echo $_SESSION["secret_access"]; // output: false
echo $secret_access; // output: false

extract_globals();  // Globals put into "normal" variables

echo $_GET["secret_access"]; // output: true
echo $_SESSION["secret_access"]; // output: false
echo $secret_access; // output: true

// VARIABLES ARE COMPROMISED!
// DO NOT USE $secret_access !
// USE $_SESSION["secret_access"] instead !!!

?>

Secondly, I would like to point out the fact that all $_POST, $_GET, and $_COOKIE variables are intrinsically unsafe anyway.  Users can create their own scripts in the language of their choosing (PHP, ASP, JSP, etc.) that generate those headers to send to your PHP program via socket connections.  PHP cannot determine that these headers are any less valid than the ones sent by a web browser, so it parses them and places them in the $_POST, $_GET, or $_COOKIE variables.

The best practice is to use $_SESSION variables to validate the user before making any decisions based on form data.  e.g.:

<?php
session_start
();
if (isset(
$_SESSION["valid"]))
{
  
// all your program decisions and database interactions can go here
  
if (isset($_POST["button_name"]))
   {
       ...
   }
   ...
}
elseif (isset(
$_POST["submit_login"]))
{
   if ((
$_POST["username"] == "foo") AND ($_POST["password"] == "bar"))
   {
      
$_SESSION["valid"] = true;
       ...
   }
   else
   {
      
session_unset();
      
session_destroy();
      
$error_msg = "Invalid username or password";
      
$result_page = "login.php";
   }
}
elseif (isset(
$logoff))
{
  
session_unset();
  
session_destroy();
  
$success_msg = "You have logged off successfully";
  
$result_page = "login.php";
}
else
{
  
session_unset();
  
session_destroy();
  
$result_page = "login.php";
}
require (
$result_page);
?>

Session variables are orders of magnitude harder to compromise than POST, GET, and COOKIE data, since the server keeps track of session id's, and the session id is unique to each client and somewhat randomly generated.  If security is an ultimate concern, then you need to use SSL in case your traffic can be sniffed (since the session cookie is passed plain text to the client).

In summary, extracting out all the superglobals to normal variable names is not a good idea for reasons of security and ambiguity, not to mention wasted CPU cycles.  For private applications (ones that you don't want just anyone to be able to access), the only ways you can prevent malicious access is to 1) use sessions to ensure that the user is valid (for that page), and 2) use SSL-encryption to prevent session-hijacking.

Kasey

in reply to:
--------------------------------------------------------------
 debabratak at softhome dot net
14-Mar-2003 12:59
After having register_globals = off, I am using the following piece of code to get all the variables created for me. I have put this code in a separate file and just make it require_once() on top of every page.

session_start();
$ArrayList = array("_GET", "_POST", "_SESSION", "_COOKIE", "_SERVER");
foreach($ArrayList as $gblArray)
{
   $keys = array_keys($$gblArray);
   foreach($keys as $key)
   {
       $$key = trim(${$gblArray}[$key]);
   }
}

This pulls out all the possible variables for me, including the predefined variables, so I can keep coding the old style. Note that, this code does not handle the $_FILE.

Hope this helps someone.
bryan at nolifeline dot com
10-May-2004 03:07
to marcbender at mail dot com

unset the globals

use a preg_replace ( pattern: |\;[^\;]*$i[^\;]*\;|Uis, replacement: ";", where $i is the name of any function/variable you wish to prevent access to.) on the code-to-be-evaled.  ideas are "global", "fopen", "mysql_connect", etc.  You know, anything that you wouldn't want to give a hyperactive 13 year old access to.

execute the code.
bryan at nolifeline dot com
10-May-2004 02:59
This code needs slightly changed...

function remap_globals() {

   global $GET_VARS, $POST_VARS, $COOKIE_VARS, $SESSION_VARS, $SERVER_VARS, $ENV_VARS;

   $parser_version = phpversion();

   if ($parser_version <= "4.1.0") {
     $GET = &$GET_VARS;
     $POST = &$POST_VARS;
     $COOKIES = &$COOKIE_VARS;
     $SESSION = &$HTTP_SESSION_VARS;
     $SERVER = &$HTTP_SERVER_VARS;
     $ENV = &$HTTP_ENV_VARS;
   }
   if ($parser_version >= "4.1.0") {
     $GET = &$_GET;
     $POST = &$_POST;
     $COOKIES  = &$_COOKIE;
     $SESSION  = &$_SESSION;
     $SERVER = &$_SERVER;
     $ENV = &$_ENV;
   }
}

Note the ampersands.  They ensure that the variables act _exactly_ like the superglobal components, ie: changing $SESSION will update $_SESSION and thus update the local session files.

So yeah.  I don't know what the PHP name for that is, but in C it's called dereferencing, and I've seen it done in function definitions in myriad people's code, but not once in a standard variable situation.  Oh well.  Can't be creative all the time ^_^
marcbender_AT_mail_DOT_com
18-Apr-2004 05:23
-Security issue-

In response to lopez at yellowspace,

You provided a method for executing potentially unsafe code:

> function safeEval($evalcode) {
>    unset($GLOBALS);
>    unset($_ENV);
>    // unset any other superglobal...
>    return eval($evalcode);
> }

Your method, though clever, won't work.  The problem is the way that PHP handles function scope.  If $evalcode contains a function declaration, and runs that function, the "unset"s will be effectively useless inside the body of that function.

Try running the above code with $evalcode set as follows:

<?php
$evalcode
='f();
function f() {
   $GLOBALS["_SERVER"] = "compromised";
}'
;
?>

Then print $_SERVER and see what you get.

Another problem is that the "global" directive will always grant access to global variables.  Try this one:

<?php
$evalcode
='global $a;
$a = "compromised";'
;
?>

$a will of course be changed at the global level.  I don't know if it's supposed to work this way, but on my system (PHP 4.3.4) you can do the same to any superglobal by importing it using "global".

As far as I can tell, there is NO way to execute potentially unsafe code without a lot of risk.  With the sloppy way that PHP deals with function scope etc., there isn't much hope that it ever will be.  What we'd need is (at least):
  - a way to disable the "global" directive (restrictive eval).
  - a way to shut off any write-access to superglobals within untrusted functions.

The first wouldn't be too hard to implement.  The second, on the other hand, is practically impossible IMHO.
mark at pitchpipe dot org
26-Oct-2003 01:21
I had always mistakenly assumed that superglobal $_COOKIE (while preferred) was identical to the outdated $HTTP_COOKIE_VARS.  However, if you assign:

$_COOKIE['destroyWorld'] = "true";
if (isset($HTTP_COOKIE_VARS['destroyWorld'])) {
   $temp =& new Armeggedon();
   $temp->pushRedButton();
 }

then the world will be safe forever.  Might throw off a newbie, or someone like me who was updating really old code bit-by-bit.
wagner at cesnet dot cz
29-Sep-2003 11:15
The redirected pages by response codes 301, 302, 303 change the request method always to GET, that's why $HTTP_POST_VARS are lost. It is described in Apache documentation.
joker at vip dot hr
08-Sep-2003 10:42
If anyone of you have a problem with uploading files with globals off here is the solution... just add this to the top of the code:

reset ($_FILES);
while (list ($key, $val) = each ($_FILES)) {
   ${$key}=$_FILES[$key]['tmp_name'];
   while (list ($key1, $val1) = each ($val)) {
       ${$key."_".$key1}=$_FILES[$key][$key1];
   }
}

   Daniel
alexsp at olywa dot net
02-May-2003 10:26
For those of us who don't have the luxery of upgrading to the latest version of PHP on all of the servers we use but want to use the same variable names that are used in the latest version for super global arrays here's a snippet of code that will help:
   // Makes available those super global arrays that are made available
   // in versions of PHP after v4.1.0.
   if (isset ($HTTP_SERVER_VARS))
   {
       $_SERVER = &$HTTP_SERVER_VARS;
   }
  
   if (isset ($HTTP_GET_VARS))
   {
       $_GET = &$HTTP_GET_VARS;
   }
  
   if (isset ($HTTP_POST_VARS))
   {
       $_POST = &$HTTP_POST_VARS;
   }
  
   if (isset ($HTTP_COOKIE_VARS))
   {
       $_COOKIE = &$HTTP_COOKIE_VARS;
   }
  
   if (isset ($HTTP_POST_FILES))
   {
       $_FILES = &$HTTP_POST_FILES;
   }
  
   if (isset ($HTTP_ENV_VARS))
   {
       $_ENV = &$HTTP_ENV_VARS;
   }
  
   if (isset ($HTTP_SESSION_VARS))
   {
       $_SESSION = &$HTTP_SESSION_VARS;
   }
The only downfall to this is that there's no way to make them super global. Chances are, though, if you're using a lot of global arrays in your code you should consider a code redesign!  :)  Hope this helps.
01-May-2003 12:06
In reply to destes at ix dot netcom dot com dot nospam:

It's possible for a HTTP client to spoof HTTP_X_FORWARDED_FOR, and set it to a fake IP number.  It's more secure to use this code and log BOTH the ip and the proxy ip.

if ($_SERVER["HTTP_X_FORWARDED_FOR"]) {
   if ($_SERVER["HTTP_CLIENT_IP"]) {
   $proxy = $_SERVER["HTTP_CLIENT_IP"];
  } else {
   $proxy = $_SERVER["REMOTE_ADDR"];
  }
  $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
} else {
  if ($_SERVER["HTTP_CLIENT_IP"]) {
   $ip = $_SERVER["HTTP_CLIENT_IP"];
  } else {
   $ip = $_SERVER["REMOTE_ADDR"];
  }
}

echo "Your IP $ip<BR>\n";
if (isset($proxy)) {
  echo "Your proxy IP is $proxy<BR>\n";
}
LouisGreen at pljg dot freeserve dot co dot uk
25-Mar-2003 01:22
It seems that when you wish to export a varible, you can do it as return $varible, return an array(), or globalise it. If you return something, information for that varible can only travel one way when the script is running, and that is out of the function.

function fn() {
   $varible = "something";

  return $variable;
}

echo fn();
OR
$newvariable = fn();

Although if global was used, it creates a pointer to a varible, whether it existed or not, and makes whatever is created in the function linked to that global pointer. So if the pointer was global $varible, and then you set a value to $varible, it would then be accessible in the global scope. But then what if you later on in the script redefine that global to equal something else. This means that whatever is put into the global array, the information that is set in the pointer, can be set at any point (overiden). Here is an example that might make this a little clearer:

function fn1() {

   global $varible; // Pointer to the global array
   $varible = "something";
}

fn1();
echo $varible; // Prints something
$varible = "12345";
echo $varible; // Prints 12345

function fn2() {

   global $varible; // Pointer to the global array
   echo $varible;
}

fn2(); // echos $varible which contains "12345"

Basically when accessing the global array, you can set it refer to something already defined or set it to something, (a pointer) such as varible you plan to create in the function, and later possibly over ride the pointer with something else.
Good Liam
19-Mar-2003 12:18
Warning:
If you use dynamic variables in a local scope, the variable doesn't "know" when it should be a superglobal.  An example will help elucidate this:

function Example($Variable_Name='_POST') {
   print_r($$Variable_Name);
} // End Example

This would print out

NULL

To use a dynamic variable to reference a superglobal, you have to declare the value (not the name) as a global:

function WorkingExample($Variable_Name='_POST') {
   global $$Variable_Name;
   print_r($$Variable_Name);
} // End WorkingExample()

This would print out the contents of your $_POST variable.

This threw me when I first tried it, but it makes sense, in a way.
LouisGreen at pljg dot freeserve dot co dot uk
12-Mar-2003 05:36
If you require access to Predefined Variables in different PHP/ servers versions and don't wish to mess about with how you access them, this little snippet of code might help you:

function fn_http_vars_access() {

   global $GET_VARS, $POST_VARS, $COOKIE_VARS, $SESSION_VARS, $SERVER_VARS, $ENV_VARS;

   $parser_version = phpversion();

   if ($parser_version <= "4.1.0") {
     $GET_VARS      = $GET_VARS;
     $POST_VARS    = $POST_VARS;
     $COOKIE_VARS  = $COOKIE_VARS;
     $SESSION_VARS  = $HTTP_SESSION_VARS;
     $SERVER_VARS  = $HTTP_SERVER_VARS;
     $ENV_VARS      = $HTTP_ENV_VARS;
   }
   if ($parser_version >= "4.1.0") {
     $GET_VARS      = $_GET;
     $POST_VARS    = $_POST;
     $COOKIE_VARS  = $_COOKIE;
     $SESSION_VARS  = $_SESSION;
     $SERVER_VARS  = $_SERVER;
     $ENV_VARS      = $_ENV;
   }
}

fn_http_vars_access();
12-Feb-2003 01:12
i just noticed that the free web server i'm running my scripts on still only knows the deprecated variable names (i.e. it uses $HTTP_POST_VARS instead of $_POST). to make scripts work both on updated servers and servers that are a bit out of date, i now use:

$variablename=(isset($_POST["variablename"])) ? $_POST["variablename"] : $HTTP_POST_VARS["variablename"];
lopez dot on dot the dot lists at yellowspace dot net
17-Jan-2003 09:11
- Security Issue and workaround -
If You use "eval()" to execute code stored in a database or elsewhere, you might find this tip useful.

Issue:
By default, all superglobals are known in every function.
Thus, if you eval database- or dynamically generated code (let's call it "potentially unsafe code"), it can use _all_ the values stored in _any_ superglobal.

Workaround:
Whenever you want to hide superglobals from use in evaluated code, wrap that eval() in an own function within which you unset() all the superglobals. The superglobals are not deleted by php in all scopes - just within that function. eg:

function safeEval($evalcode) {
   unset($GLOBALS);
   unset($_ENV);
   // unset any other superglobal...
   return eval($evalcode);
}

(This example assumes that the eval returns something with 'return')

In addition, by defining such a function outside classes, in the global scope, you'll make sure as well that the evaluated ('unsafe') code doesn't have access to the object variables ($this-> ...).
pschulten at NOSPMweb dot de
14-Aug-2002 04:30
In addition to slandau@miticom.com (14-Jan-2002 08:03).
You definetly restored my sanity, thanks.

If you post multiple textfields with the same name, you can also give them indices e.g.:
<input type='Text' name='some_date[year]' value='2002'>
<input type='Text' name='some_date[month]' value='08'>
<input type='Text' name='some_date[day]' value='02'>

and access them thru:
$_POST['some_date']['year']
$_POST['some_date']['month']
$_POST['some_date']['day']
08-Jul-2002 04:46
Wouldn't it be great if there was a variable called $_SERVER["PATH_USERHOME"]. Here is how to set it yourself:

$path_fs = split ("/", ltrim ($_SERVER["PATH_TRANSLATED"], "/"));
$path_fs_rev = array_reverse ($path_fs);

$path_http = split ("/", ltrim ($_SERVER["PHP_SELF"], "/"));
$path_http_rev = array_reverse ($path_http);

$num_same = 0;
while ($path_fs_rev[$num_same] == $path_http_rev[$num_same]) {
   $num_same++;
}

$path_userhome = array ();
$numdirs_userhome = sizeof ($path_http) - $num_same;
echo $numdirs_userhome;

for ($i = 0; $i < $numdirs_userhome; $i++) {
   array_push ($path_userhome, $path_http[$i]);
}

$_SERVER["PATH_USERHOME"] = "/" . implode ("/", $path_userhome) . "/";

print_r ($_SERVER["PATH_USERHOME"]);

;) Happy programming,

Peder
juancri at TAGnet dot org
31-May-2002 11:52
If you try this:

<FORM action="hola">
  ....
</FORM>

and hola is a directory, you have to write the final slash (/) because the page is redirected from hola to hola/ and you'll lost the POST variables.
admin at SexDev dot com
25-Apr-2002 04:17
The problem with empty HTTP_X_FORWARDED_FOR is because of anonymous proxy servers:

Anonymous - HTTP Proxy server does not send HTTP_X_FORWARDED_FOR variable to host, this improves privacy since your IP address cannot be logged.

High anonymity - HTTP Servers of this type don’t send HTTP_X_FORWARDED_FOR, HTTP_VIA and HTTP_PROXY_CONNECTION variables. Host doesn’t even know you are using proxy server an of course it doesn’t know your IP address.
rick@independence,netI
23-Jul-2001 09:13
It should be noted that $HTTP_RAW_POST_DATA only exists if the encoding type of the data is -not- the default of application/x-www.form-urlencoded, and so, to accessing raw post data from an HTTP form requires setting enctype= in your HTML.
m dot crawford at nospam dot home dot com
10-Jun-2001 07:48
$GLOBALS["HTTP_RAW_POST_DATA"] contains the raw POSTed data from a request.  Also available (obviously) as $HTTP_RAW_POST_DATA in the global scope.  Thanks to Manuel Lemos' SOAP server class for shedding some light on the subject.
mike at dbeat dot com
22-Nov-2000 09:30
If you're running PHP as a shell script, and you want to use the argv and argc arrays to get command-line arguments, make sure you have register_argc_argv  =  on.  If you're using the 'optimized' php.ini, this defaults to off.

<VariablesVariable scope>
 Last updated: Thu, 19 May 2005
Copyright © 2001-2005 The PHP Group
All rights reserved.
This unofficial mirror is operated at: The Server Pages
Last updated: Thu May 19 18:35:34 2005 EDT