Predefined Variables

PHP provides a large number of predefined variables to all scripts. The variables represent everything from external variables to built-in environment variables, last error messages to last retrieved headers.

See also the FAQ titled "How does register_globals affect me?"

Table of Contents

add a note add a note

User Contributed Notes 43 notes

up
30
New York PHP
12 years ago
Warning: $_SERVER['PHP_SELF'] can include arbitrary user input. The documentation should be updated to reflect this.

The request "http://example.com/info.php/attack%20here" will run /info.php, but in Apache $_SERVER['PHP_SELF'] will equal "/info.php/attack here". This is a feature, but it means that PHP_SELF must be treated as user input.

The attack string could contain urlencoded HTML and JavaScript (cross-site scripting) or it could contain urlencoded linebreaks (HTTP response-splitting).

The use of $_SERVER['SCRIPT_NAME'] is recommended instead.
up
2
mrnopersonality at yahoo dot com
12 years ago
Nothing about the message-body ...

You can get cookies, session variables, headers, the request-uri , the request method, etc but not the message body. You may want it sometimes when your page is to be requested with the POST method.

Maybe they should have mentioned $HTTP_RAW_POST_DATA or php://stdin
up
3
josh,endquote,com
13 years ago
Running PHP 4.3 under IIS 5 on Windows XP, there is no $_SERVER['REQUEST_URI'] variable. This seems to fix it:

if(!isset($_SERVER['REQUEST_URI'])) {
    $_SERVER['REQUEST_URI'] = substr($_SERVER['argv'][0], strpos($_SERVER['argv'][0], ';') + 1);
}
up
3
mfyahya at gmail dot com
12 years ago
If you use Apache's redirection features for custom error pages or whatever, the following Apache's REDIRECT variables are also available in $_SERVER:
$_SERVER['REDIRECT_UNIQUE_ID]'
$_SERVER['REDIRECT_SCRIPT_URL]'
$_SERVER['REDIRECT_SCRIPT_URI]'
$_SERVER['REDIRECT_SITE_ROOT]'
$_SERVER['REDIRECT_SITE_HTMLROOT]'
$_SERVER['REDIRECT_SITE_CGIROOT]'
$_SERVER['REDIRECT_STATUS]'
$_SERVER['REDIRECT_QUERY_STRING]'
$_SERVER['REDIRECT_URL]'

I'm not sure if this is a complete list though
up
2
Gregory Boshoff
12 years ago
The Environment variable $ENV is useful for coding portable platform specific application constants.

// Define a Windows or else Linux root directory path
$_ENV['OS'] == 'Windows_NT' ? $path = 'L:\\www\\' : $path = ' /var/www/';

define('PATH', $path);

echo PATH;
up
3
jameslporter at gmail dot com
11 years ago
Refer to CanonicalName if you are not getting the ServerName in the $_SERVER[SERVER_NAME] variable....This was a pain to figure out for me...now it works as expected by turning canonical naming on.

http://www.apacheref.com/ref/http_core/UseCanonicalName.html
up
1
Ben XO
11 years ago
So you have an application in your web space, with a URL such as this:

http://<host>/<installation_path>/

and pages such as

http://<host>/<installation_path>/subfolder1/subfolder2/page.php

You have a file called config.php in <installation_path> which is include()d by all pages (in subfolders or not).

How to work out <installation_path> without hard-coding it into a config file?

<?php

// this is config.php, and it is in <installation_path>
// it is included by <installation_path>/page.php
// it is included by <installation_path>/subfolder/page2.php
// etc

$_REAL_SCRIPT_DIR = realpath(dirname($_SERVER['SCRIPT_FILENAME'])); // filesystem path of this page's directory (page.php)
$_REAL_BASE_DIR = realpath(dirname(__FILE__)); // filesystem path of this file's directory (config.php)
$_MY_PATH_PART = substr( $_REAL_SCRIPT_DIR, strlen($_REAL_BASE_DIR)); // just the subfolder part between <installation_path> and the page

$INSTALLATION_PATH = $_MY_PATH_PART
   
? substr( dirname($_SERVER['SCRIPT_NAME']), 0, -strlen($_MY_PATH_PART) )
    :
dirname($_SERVER['SCRIPT_NAME'])
;
// we subtract the subfolder part from the end of <installation_path>, leaving us with just <installation_path> :)

?>
up
1
niles AT atheos DOT net
12 years ago
If your having problems returning $_SERVER variables using apache, be sure you enable:

ExtendedStatus On

in your httpd.conf file.

If it's off, then things like $_SERVER['HTTP_HOST'] won't be present.
up
0
justin dot (nospam)george at gmail dot com
11 years ago
Note that it's a very, very bad idea to append to global variables in a loop, unless you really, really mean to do so in a global context. I just a while ago hung my server with a snippet of code like this:

<?php
$host 
= $_SERVER['HTTP_HOST'];
$uri  = rtrim($_SERVER['PHP_SELF'], "/\\");

  
$GLOBALS['SITE_ROOT'] = "http://$host$uri";

while (
$i < somenumber)
readfile($GLOBALS['SITE_ROOT'] = $GLOBALS['SITE_ROOT'] . '/this/file.php');
$i++
}
?>

While it is an entertaining and unusual method of creating very long URLs and breaking servers, it's a pretty awesomely bad idea

(Especially considering that the script in question ran concurrently with others of it's type, so the value in $GLOBALS['SITE_ROOT'] was unknown.)
up
0
chris at vault5 dot com
11 years ago
Since $_SERVER['DOCUMENT_ROOT'] is not always present, the following will provide it where $_SERVER dosen't.

<?php
function resolveDocumentRoot() {
   
$current_script = dirname($_SERVER['SCRIPT_NAME']);
   
$current_path   = dirname($_SERVER['SCRIPT_FILENAME']);
   
   
/* work out how many folders we are away from document_root
       by working out how many folders deep we are from the url.
       this isn't fool proof */
   
$adjust = explode("/", $current_script);
   
$adjust = count($adjust)-1;
   
   
/* move up the path with ../ */
   
$traverse = str_repeat("../", $adjust);
   
$adjusted_path = sprintf("%s/%s", $current_path, $traverse);

   
/* real path expands the ../'s to the correct folder names */
   
return realpath($adjusted_path);   
}

?>

It counts the number of folders down the path we are in the URL, then moves that number of folders up the current path... end result should be the document root :)

It wont work with virtual folders or in any situation where the folder in the URL dosen't map to a real folder on the disk (like when using rewrites).
up
0
marcus at lastcraft dot com
12 years ago
The variable $php_errormsg is not populated if you have XDebug running.
up
-1
autofei at gmail dot com
7 years ago
if you try to run php through command line, for example: php.exe c:\AppServ\www\cron_cache.php. You better avoid to use $_SERVER['DOCUMENT_ROOT'], because it will return nothing. Instead, you can use dirname(__FILE__). The reason to use command line running php is set it as Windows Scheduled Tasks. I did not test under Linux environment, but might be same.
up
-1
Nicolae Namolovan
9 years ago
SECURITY RISK !

Never ever trust the values that comes from $_SERVER.

HTTP_X_FORWARDED, HTTP_X_FORWARDED_FOR, HTTP_FORWARDED_FOR, HTTP_FORWARDED, etc.. can be spoofed !

To get the ip of user, use only $_SERVER['REMOTE_ADDR'], otherwise the 'ip' of user can be easily changed by sending a HTTP_X_* header, so user can escape a ban or spoof a trusted ip.

Of course this is well know, but I don't see it mentioned in these notes..

If you use the ip only for tracking (not for any security features like banning or allow access to something by ip), you can also use HTTP_X_FORWARDED to get user's ip what are behind proxy.
up
-1
youdontmeanmuch [at] yahoo.com
13 years ago
Be carful when using $_SERVER['DOCUMENT_ROOT']; in your applications where you want to distribute them to other people with different server types. It isnt always supported by the webserver (IIS).
up
-1
php-net dot ucn dot extranet dot sys at dark-chiaki dot net
9 years ago
In addition to mfyahya at gmail dot com (2007-06-07 03:33):

If You are working with the Apache module mod_rewrite and want to set some environment vars, the Apache manual says this vars could be accessed in CGI using $ENV{VAR}. In PHP You might want to write $_ENV['VAR'] to get the value of VAR, but You have to access if via $_SERVER, and in some different ways:

1. Example: .htaccess and example.php

RewriteEngine on
RewriteRule ^?var1=([^;]*);var2=([^;]*)$ \
- [E=VAR1:$1,E=VAR2:$2]

<?php echo($_SERVER['VAR1']."\r\n"
         
.$_SERVER['VAR2']); ?>

2. Example: .htaccess and index.php

RewriteEngine on
RewriteRule ^index\.php$ - [L]
RewriteRule ?var1=([^;]*);var2=([^;]*)$ \
index.php [E=VAR1:$1,E=VAR2:$2]

<?php echo($_SERVER['REDIRECT_VAR1']."\r\n"
         
.$_SERVER['REDIRECT_VAR2']); ?>

Note: If any RewriteRule matches, an internal redirect than restarts (after the last defined rule, or immediately after the matched rule having a L-flag) checking the entire rule set again. For an internal redirect every defined VAR gets an 'REDIRECT_' prefix, i.e. VAR1 will be REDIRECT_VAR1, VAR2 will be REDIRECT_VAR2.

Of course, You can (additionally) redefine the original VAR:

RewriteEngine on
RewriteRule ^index\.php$ \
- [E=VAR1:%{REDIRECT_VAR1},E=VAR2:%{REDIRECT_VAR2},L]
RewriteRule ?var1=([^;]*);var2=([^;]*)$ \
index.php [E=VAR1:$1,E=VAR2:$2]

With this, You will have $_SERVER['REDIRECT_VAR*'] -and- $_SERVER['VAR*'].

***

The given examples are only for explanation, in any case they are not intended to fit Your needs. The "\<CRLF><SP>" in the .htaccess examples are only for display purpose, they should not occur in a real .htaccess file. The argument separator ';' in links can also be '&', but this may cause some trouble with HTML/XHTML. See the following pages for more information about this issue:
- http://www.w3.org/TR/html4/appendix/notes.html#h-B.2.2
- http://www.w3.org/QA/2005/04/php-session
up
-1
todd dot kisov at yahoo dot com
11 years ago
To convert query string parameter values ($_GET, $_REQUEST), which include escaped Unicode values resulting from applying the JavaScript "escape" function to a Unicode string (%uNNNN%uNNNN%uNNNN) fast and simple is to use PECL JSON extension:

function JavaScript_Unicode_URL_2_Str($js_uni_str) {
        $res = preg_replace('/%u([[:alnum:]]{4})/', '\\u\1', $js_uni_str);
        $res = str_replace('"', '\"', $res); // if in str "
        $res = json_decode('["'.$res.'"]'); // JavaScrip array with string element
        $res = $res[0];
        $res = iconv('UTF-8', ini_get('default_charset'), $res);
        return $res;
    }
up
-1
Aardvark
11 years ago
$_GET may not handle query string parameter values which include escaped Unicode values resulting from applying the JavaScript "escape" function to a Unicode string.
To handle this the query parameter value can be obtained  using a function such as:

function getQueryParameter ($strParam) {
  $aParamList = explode('&', $_SERVER['QUERY_STRING']);
  $i = 0;
  while ($i < count($aParamList)) {
    $aParam = split('=', $aParamList[$i]);
    if ($strParam == $aParam[0]) {
      return $aParam[1];
    }
  }
  return "";
}

or by directly building an array or query string values and then processing the parameter string using a function such as the "unescape" function which can be found at http://www.kanolife.com/escape/2006/03/unicode-url-escapes-in-php.html (or http://www.kanolife.com/escape/ for related info).
up
-1
nathan
11 years ago
Also on using IPs to look up country & city, note that what you get might not be entirely accurate.  If their ISP is based in a different city or province/state, the IPs may be owned by the head office, and used across several areas. 
You also have rarer situations where they might be SSHed into another server, on the road, at work, at a friend's...  It's a nice idea, but as the example code shows, it should only be used to set defaults.
up
-1
daniel at softel dot jp
12 years ago
Note that $php_errormsg may contain a newline character. This can be problematic if you are trying to output it with a JavaScript "alert()" for example.
up
-2
dusted at dusted dot dk
6 years ago
I use HTTP_X_FORWARDED_FOR because my webserver is behind a reverse proxy.
This can be made secure:
Configure the reverse proxy to block this field, and override it correctly.
Configure the apache server to only accept incoming connections from the reverse proxy.
up
-1
david at grant dot org dot uk
13 years ago
$_SERVER['DOCUMENT_ROOT'] *is* supported by IIS, although only when running PHP as an ISAPI module.