PHP_SELF vs PATH_INFO vs SCRIPT_NAME vs REQUEST_URI
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):
[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
[PHP_SELF] => /index.php
[PATH_INFO] IS NOT AVAILABLE (fallback to REQUEST_URI in your script)
[REQUEST_URI] => /
[QUERY_STRING] =>
Path
[PHP_SELF] => /index.php/test
[PATH_INFO] => /test
[REQUEST_URI] => /test
[QUERY_STRING] =>
Query String
[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
[REQUEST_URI] => /
[QUERY_STRING] =>
Path
[REQUEST_URI] => /test
[QUERY_STRING] => url=test
Query String
[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
[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
[PHP_SELF] => /index.php/test
[PATH_INFO] => /test
[REQUEST_URI] => /test
[QUERY_STRING] =>
[REDIRECT_LANGUAGE] =>
Language
[PHP_SELF] => /index.php/
[PATH_INFO] => /
[REQUEST_URI] => /en
[QUERY_STRING] =>
[REDIRECT_LANGUAGE] => en
Language path
[PHP_SELF] => /index.php/test
[PATH_INFO] => /test
[REQUEST_URI] => /en/test
[REDIRECT_LANGUAGE] => en
Language Query string
[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
fromhttp://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
- Client sends server an HTTP request
REQUEST_URI
- Server performs any URL rewriting from .htaccess files, etc. to get
PHP_SELF
- Server separates
PHP_SELF
intoSCRIPT_FILENAME
+PATH_INFO
- Server performs alias resolution and converts the entire url path to a system file path to get
SCRIPT_FILENAME
- 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
Related videos on Youtube
Eli
Updated on July 08, 2022Comments
-
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 seeindex.php
in the URI. For example,http://www.example.com/faq/whatever
will route tohttp://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 usedmod_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 alwaysindex.php
. I can get it fromREQUEST_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 betweenPHP_SELF
,PATH_INFO
,SCRIPT_NAME
, andREQUEST_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 over 15 yearsIs it always the complete URI?
-
David Padbury over 15 yearsTypically, you can run into issues with apache on windows, but it's only for URI's that don't resolve.
-
Eli over 15 yearsThank 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 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 about 13 years+1: 1st time in my life I understood the difference. They should update PHP documentaion with your answer
-
Kenneth over 12 yearsWhy reinvent the wheel? This data is much more easily accessed!
-
SimonSimCity about 12 yearsThis 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 about 12 yearsExample1: [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 about 12 yearsYou 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 about 12 yearsThis was great. Thanks for your help!
-
Fabrício Matté over 11 yearsI've tested this on 5.2.17 too and there's no
/
at the end of theSCRIPT_NAME
. This seems to be consistent in PHP 5.2-5.4 then, considering editing the answer to reflect that. -
icc97 over 10 yearsYou missed off
REQUEST_URI
vsPHP_SELF
here they differ if you request example.com :[REQUEST_URI] => /
and[PHP_SELF] => /index.php
-
ChandlerQ over 9 yearsThis 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 useSCRIPT_NAME
to get the REAL requested page on Apache. -
Admin over 8 yearsOdin'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 over 8 yearsThis 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 over 8 yearsHi 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 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 over 8 yearsIn 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 over 8 yearsI 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 over 8 yearsExample 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 over 8 yearsThis 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 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 over 7 yearsAnd 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 aurl
param on the initial request) or worse, be vulnerable to XSS attacks. -
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 over 5 yearsworth noting this apache bug: bz.apache.org/bugzilla/show_bug.cgi?id=40102
-
Jamie Robinson about 5 yearsAlso 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
. :)