PHP_SELF vs PATH_INFO vs SCRIPT_NAME vs REQUEST_URI

83,262

Solution 1

The PHP documentation can tell you the difference:

'PHP_SELF'

The filename of the currently executing script, relative to the document root. For instance, $_SERVER['PHP_SELF'] in a script at the address http://example.com/test.php/foo.bar would be /test.php/foo.bar. The __FILE__ constant contains the full path and filename of the current (i.e. included) file. If PHP is running as a command-line processor this variable contains the script name since PHP 4.3.0. Previously it was not available.

'SCRIPT_NAME'

Contains the current script's path. This is useful for pages which need to point to themselves. The __FILE__ constant contains the full path and filename of the current (i.e. included) file.

'REQUEST_URI'

The URI which was given in order to access this page; for instance, '/index.html'.

PATH_INFO doesn't seem to be documented...

Solution 2

Some practical examples of the differences between these variables:
Example 1. PHP_SELF is different from SCRIPT_NAME only when requested url is in form:
http://example.com/test.php/foo/bar

[PHP_SELF] => /test.php/foo/bar
[SCRIPT_NAME] => /test.php

(this seems to be the only case when PATH_INFO contains sensible information [PATH_INFO] => /foo/bar) Note: this used to be different in some older PHP versions (<= 5.0 ?).

Example 2. REQUEST_URI is different from SCRIPT_NAME when a non-empty query string is entered:
http://example.com/test.php?foo=bar

[SCRIPT_NAME] => /test.php
[REQUEST_URI] => /test.php?foo=bar

Example 3. REQUEST_URI is different from SCRIPT_NAME when server-side redirecton is in effect (for example mod_rewrite on apache):

http://example.com/test.php

[REQUEST_URI] => /test.php
[SCRIPT_NAME] => /test2.php

Example 4. REQUEST_URI is different from SCRIPT_NAME when handling HTTP errors with scripts.
Using apache directive ErrorDocument 404 /404error.php
http://example.com/test.php

[REQUEST_URI] => /test.php
[SCRIPT_NAME] => /404error.php

On IIS server using custom error pages
http://example.com/test.php

[SCRIPT_NAME] => /404error.php
[REQUEST_URI] => /404error.php?404;http://example.com/test.php

Solution 3

PATH_INFO is only available when using htaccess like this:

Example 1

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^(favicon\.ico|robots\.txt)
RewriteRule ^(.*)$ index.php/$1 [L]

Remains the same

[SCRIPT_NAME] => /index.php

Root

http://domain.com/

[PHP_SELF]     => /index.php
[PATH_INFO] IS NOT AVAILABLE (fallback to REQUEST_URI in your script)
[REQUEST_URI]  => /
[QUERY_STRING] => 

Path

http://domain.com/test

[PHP_SELF]     => /index.php/test
[PATH_INFO]    => /test
[REQUEST_URI]  => /test
[QUERY_STRING] => 

Query String

http://domain.com/test?123

[PHP_SELF]     => /index.php/test
[PATH_INFO]    => /test
[REQUEST_URI]  => /test?123
[QUERY_STRING] => 123

Example 2

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^(favicon\.ico|robots\.txt)
RewriteRule ^(.*)$ index.php?url=$1 [L,QSA]

Remains the same

[SCRIPT_NAME]  => /index.php
[PHP_SELF]     => /index.php
[PATH_INFO] IS NOT AVAILABLE (fallback to REQUEST_URI in your script)

Root

http://domain.com/

[REQUEST_URI]  => /
[QUERY_STRING] => 

Path

http://domain.com/test

[REQUEST_URI]  => /test
[QUERY_STRING] => url=test

Query String

http://domain.com/test?123

[REQUEST_URI]  => /test?123
[QUERY_STRING] => url=test&123

Example 3

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^(favicon\.ico|robots\.txt)
RewriteRule ^(([a-z]{2})|(([a-z]{2})/)?(.*))$ index.php/$5 [NC,L,E=LANGUAGE:$2$4]

or

RewriteRule ^([a-z]{2})(/(.*))?$ $3 [NC,L,E=LANGUAGE:$1]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^(favicon\.ico|robots\.txt)
RewriteRule ^(.*)$ index.php/$1 [L]

Remains the same

[SCRIPT_NAME] => /index.php

Root

http://domain.com/

[PHP_SELF]          => /index.php
[PATH_INFO] IS NOT AVAILABLE (fallback to REQUEST_URI in your script)
[REQUEST_URI]       => /
[QUERY_STRING]      => 
[REDIRECT_LANGUAGE] IS NOT AVAILABLE

Path

http://domain.com/test

[PHP_SELF]          => /index.php/test
[PATH_INFO]         => /test
[REQUEST_URI]       => /test
[QUERY_STRING]      => 
[REDIRECT_LANGUAGE] => 

Language

http://domain.com/en

[PHP_SELF]          => /index.php/
[PATH_INFO]         => /
[REQUEST_URI]       => /en
[QUERY_STRING]      => 
[REDIRECT_LANGUAGE] => en

Language path

http://domain.com/en/test

[PHP_SELF]          => /index.php/test
[PATH_INFO]         => /test
[REQUEST_URI]       => /en/test
[REDIRECT_LANGUAGE] => en

Language Query string

http://domain.com/en/test?123

[PHP_SELF]          => /index.php/test
[PATH_INFO]         => /test
[REQUEST_URI]       => /en/test?123
[QUERY_STRING]      => 123
[REDIRECT_LANGUAGE] => en

Solution 4

PHP Paths

    $_SERVER['REQUEST_URI']    = Web path, requested URI
    $_SERVER['PHP_SELF']    = Web path, requested file + path info
    $_SERVER['SCRIPT_NAME']    = Web path, requested file
    $_SERVER['SCRIPT_FILENAME']   = File path, requested file
    __FILE__    = File path, current file

Where

  • File path is a system file path like /var/www/index.php, after alias resolution
  • Web path is a server document path like /index.php from http://foo.com/index.php, and may not even match any file
  • Current file means the included script file, not any script that includes it
  • Requested file means the includer script file, not the included one
  • URI is the HTTP request like /index.php?foo=bar, before any URL rewriting
  • Path info is any extra Apache data located after the script name but before the query string

Order of Operation

  1. Client sends server an HTTP request REQUEST_URI
  2. Server performs any URL rewriting from .htaccess files, etc. to get PHP_SELF
  3. Server separates PHP_SELF into SCRIPT_FILENAME + PATH_INFO
  4. Server performs alias resolution and converts the entire url path to a system file path to get SCRIPT_FILENAME
  5. Resulting script file may include others, where __FILE__ refers to the path to the current file

Solution 5

You may want to look into the URI Class and make use of $this->uri->uri_string()

Returns a string with the complete URI.

For example, if this is your full URL:

http://example.com/index.php/news/local/345

The function would return this:

/news/local/345

Or you could make use of the segments to drill down specific areas without having to come up with parsing/regex values

Share:
83,262

Related videos on Youtube

Eli
Author by

Eli

Updated on July 08, 2022

Comments

  • Eli
    Eli almost 2 years

    I am building a PHP application in CodeIgniter. CodeIgniter sends all requests to the main controller: index.php. However, I don't like to see index.php in the URI. For example, http://www.example.com/faq/whatever will route to http://www.example.com/index.php/faq/whatever. I need a reliable way for a script to know what it's address is, so it will know what to do with the navigation. I've used mod_rewrite, as per CodeIgniter documentation.

    The rule is as follows:

    RewriteEngine on
    RewriteCond $1 !^(images|inc|favicon\.ico|index\.php|robots\.txt)
    RewriteRule ^(.*)$ /index.php/$1 [L] 
    

    Normally, I would just check php_self, but in this case it's always index.php. I can get it from REQUEST_URI, PATH_INFO, etc., but I'm trying to decide which will be most reliable. Does anyone know (or know where to find) the real difference between PHP_SELF, PATH_INFO, SCRIPT_NAME, and REQUEST_URI? Thanks for your help!

    Note: I've had to add spaces, as SO sees the underscore, and makes it italic for some reason.

    Updated: Fixed the spaces.

  • Eli
    Eli over 15 years
    Is it always the complete URI?
  • David Padbury
    David Padbury over 15 years
    Typically, you can run into issues with apache on windows, but it's only for URI's that don't resolve.
  • Eli
    Eli over 15 years
    Thank you - this is a good idea, but I am using these in a pre-system hook that will need to run before the controller is up and running.
  • Alix Axel
    Alix Axel almost 14 years
    +1, "An example is not a way to learn, it's the only way to learn." - I always have to recheck this stuff, very nice research on the 404 errors. =)
  • Marco Demaio
    Marco Demaio about 13 years
    +1: 1st time in my life I understood the difference. They should update PHP documentaion with your answer
  • Kenneth
    Kenneth over 12 years
    Why reinvent the wheel? This data is much more easily accessed!
  • SimonSimCity
    SimonSimCity about 12 years
    This is most likely not about the PHP documentation but the CGI :) And there PATH_INFO is documented: tools.ietf.org/html/rfc3875#section-4 But there are some known issues that Apache and nginx are not always giving this variable.
  • Dawid Ohia
    Dawid Ohia about 12 years
    Example1: [SCRIPT_NAME] => /test.php/ There should be no "/" at the end: Example1: [SCRIPT_NAME] => /test.php Anyway that's what I see in PHP 5.3.6 . Nice examples.
  • Odin
    Odin about 12 years
    You are correct JohnM2, i have now checked on PHP 5.4 and the result for URL /pinfo.php/first/second?third=fourth is as follows: QUERY_STRING => third=fourth REQUEST_URI => /pinfo.php/first/second?third=fourth SCRIPT_NAME => /pinfo.php PATH_INFO => /first/second
  • Gabriel Fair
    Gabriel Fair about 12 years
    This was great. Thanks for your help!
  • Fabrício Matté
    Fabrício Matté over 11 years
    I've tested this on 5.2.17 too and there's no / at the end of the SCRIPT_NAME. This seems to be consistent in PHP 5.2-5.4 then, considering editing the answer to reflect that.
  • icc97
    icc97 over 10 years
    You missed off REQUEST_URI vs PHP_SELF here they differ if you request example.com : [REQUEST_URI] => / and [PHP_SELF] => /index.php
  • ChandlerQ
    ChandlerQ over 9 years
    This is very helpful especially the Example 4 error handling part. Recently I find that some programmers are using REQUEST_URI as conditions, then provide different header/footer respectively. It works in most cases but will have problems with 404/403 pages. I think a better way is to use SCRIPT_NAME to get the REAL requested page on Apache.
  • Admin
    Admin over 8 years
    Odin's answer below adds useful explanations that are complemented with examples. I find it hard to understand what these variables represent in a general context with a path_info, a query string, some redirection, some aliases, on different operating systems, from CLI vs SERVER, etc.
  • Admin
    Admin over 8 years
    This is good. Here are my comments. First, both $_SERVER['SCRIPT_NAME'] and $_SERVER['SCRIPT_FILENAME'] are script name, except that the later is after aliases are executed. Second, $_SERVER['PHP_SELF'] is not the script, but the script + the path info. Again, $_SERVER['SCRIPT_NAME'] is the script (before aliases). Finally, it is useful to know at what stage, after or before rewrite-rules, after or before aliases, these variables are defined. See my answer.
  • Beejor
    Beejor over 8 years
    Hi Dominic108, thanks for the revision. I do think it's useful to include the rewrite info. To me it was implied, but to others it may not be that intuitive.
  • Beejor
    Beejor over 8 years
    @Dominic108 I revised my answer based on your suggestions, tidied things up a bit, and added an Order of Operation section. Let me know what you think. Thanks!
  • Admin
    Admin over 8 years
    In your order, you have to swap $_SERVER['SCRIPT_NAME'] and  $_SERVER['PHP_SELF'] , because mod_rewrite create the entire path, which is $_SERVER['PHP_SELF'] . The separation occurs next. Note that aliases also consider the entire path to define the script filename, but the separation that defined script_name and path_info already occurred, so they will not be affected.
  • Admin
    Admin over 8 years
    I know that it is not part of the question, but it is useful to mention that [REQUEST_URI] is defined before URL rewriting, including mod_dir rewrite as pointed out by @icc97. [PHP_SELF] = [SCRIPT_NAME] + [PATH_INFO] is defined after mod_dir and mod_rewrite, but before aliases are resolved. Aliases can change the complete URL path (which PHP names [PHP_SELF]) to obtain the [SCRIPT_FILENAME], which is the actual script on the file system. To be slightly more complete, let's add that the script can include other files and __FILE__ is the current file.
  • Admin
    Admin over 8 years
    Example 1 also says that [REQUEST_URI] is different from [SCRIPT_NAME] when [PATH_INFO] is not empty. It was understood, but it was not explicitly written. Example [REQUEST_URI] => /test.php/foo.bar, [SCRIPT_NAME] => /test.php
  • Admin
    Admin over 8 years
    This answer is written in a way that suggests that only url rewritting can create a path_info, but, of course, the path info can be entered directly in the original URL.
  • Beejor
    Beejor over 8 years
    @Dominic108 I revised my answer again. For some reason your edit proposal was rejected, though as far as I know, you are correct that two of my items were out of order. I'm not as familiar with aliases, so I'm relying on your expertise for that part. Thanks again!
  • MrWhite
    MrWhite over 7 years
    And there is additional complexity if the original request is expected to have a query string. In its current state, the above code will simply overwrite the query string. If you merge query strings (QSA flag) then query string params can potentially be overwritten (for instance, if you needed a url param on the initial request) or worse, be vulnerable to XSS attacks.
  • dallin
    dallin over 5 years
    -1 Just as an explanation as to why I downvoted: the entire reason I came to this post is because the documentation is not clear. Odin's answer below provides a clear explanation of the differences between these variables. I feel like it's an insufficient answer to just copy and paste easily found yet also insufficient documentation. I believe most people would have had to already visit the documentation to even know about the list of elements in the $_SERVER variable mentioned above.
  • Brad Kent
    Brad Kent over 5 years
    worth noting this apache bug: bz.apache.org/bugzilla/show_bug.cgi?id=40102
  • Jamie Robinson
    Jamie Robinson about 5 years
    Also worth putting in an example of domain traversal, as they differ in this way as well. For instance in http://example.com/something/../test.php, the REQUEST_URI will be /something/../test.php and the SCRIPT_NAME will be /test.php. :)