Reputation: 99398
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.
Upvotes: 119
Views: 89404
Reputation: 176655
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'
Contains any client-provided pathname information trailing the actual script filename but preceding the query string, if available. For instance, if the current script was accessed via the URI http://www.example.com/php/path_info.php/some/stuff?foo=bar, then $_SERVER['PATH_INFO'] would contain /some/stuff.
Upvotes: 55
Reputation: 5141
assume scheme://host/path/script.php
after script.php
there will be two possiblitiy:
1- query string like scheme://host/path/script.php?qs=a
2- more path info like scheme://host/path/script.php/more/path
now we have a very simple rules:
property | what is included | e.g.: http://localhost/dashboard/paln5/st1.php/a/b?c=d |
---|---|---|
REQUEST_URI | everything afterward is included | /dashboard/paln5/st1.php/a/b?c=d |
PHP_SELF | just more path included | /dashboard/paln5/st1.php/a/b |
SCRIPT_NAME | nothing afterward is included | /dashboard/paln5/st1.php |
Upvotes: -1
Reputation: 7880
If you ever forget which variables do what, you can write a little script that uses phpinfo() and call it from a URL with a query string. Since server software installations present the variables that PHP returns it's always a good idea to check the machine's output in case rewrites at the server config file are causing different results than expected. Save it as something like _inf0.php
:
<?php
$my_ip = '0.0.0.0';
if($_SERVER['REMOTE_ADDR']==$my_ip){
phpinfo();
} else {
//something
}
Then you would call /_inf0.php?q=500
Upvotes: 1
Reputation: 9398
$_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
/var/www/index.php
, after alias resolution/index.php
from
http://foo.com/index.php
, and may not even match any file/index.php?foo=bar
, before any URL rewritingREQUEST_URI
PHP_SELF
PHP_SELF
into SCRIPT_FILENAME
+ PATH_INFO
SCRIPT_FILENAME
__FILE__
refers to the path to the current fileUpvotes: 17
Reputation:
There is very little to add to Odin's answer. I just felt to provide a complete example from the HTTP request to the actual file on the file system to illustrate the effects of URL rewriting and aliases. On the file system the script /var/www/test/php/script.php
is
<?php
include ("script_included.php")
?>
where /var/www/test/php/script_included.php
is
<?php
echo "REQUEST_URI: " . $_SERVER['REQUEST_URI'] . "<br>";
echo "PHP_SELF: " . $_SERVER['PHP_SELF'] . "<br>";
echo "QUERY_STRING: " . $_SERVER['QUERY_STRING'] . "<br>";
echo "SCRIPT_NAME: " . $_SERVER['SCRIPT_NAME'] . "<br>";
echo "PATH_INFO: " . $_SERVER['PATH_INFO'] . "<br>";
echo "SCRIPT_FILENAME: " . $_SERVER['SCRIPT_FILENAME'] . "<br>";
echo "__FILE__ : " . __FILE__ . "<br>";
?>
and /var/www/test/.htaccess
is
RewriteEngine On
RewriteRule before_rewrite/script.php/path/(.*) after_rewrite/script.php/path/$1
and the Apache configuration file includes the alias
Alias /test/after_rewrite/ /var/www/test/php/
and the http request is
www.example.com/test/before_rewrite/script.php/path/info?q=helloword
The output will be
REQUEST_URI: /test/before_rewrite/script.php/path/info?q=helloword
PHP_SELF: /test/after_rewrite/script.php/path/info
QUERY_STRING: q=helloword
SCRIPT_NAME: /test/after_rewrite/script.php
PATH_INFO: /path/info
SCRIPT_FILENAME: /var/www/test/php/script.php
__FILE__ : /var/www/test/php/script_included.php
The following always holds
PHP_SELF = SCRIPT_NAME + PATH_INFO = full url path between domain and query string.
If there is no mod_rewrite, mod_dir, ErrorDocument rewrite or any form of URL rewriting, we also have
REQUEST_URI = PHP_SELF + ? + QUERY_STRING
The aliases affect the system file paths SCRIPT_FILENAME
and __FILE__
, not the URL paths, which are defined before - see exceptions below. Aliases might use the entire URL path, including PATH_INFO
. There could be no connection at all between SCRIPT_NAME
and SCRIPT_FILENAME
.
It is not totally exact that aliases are not resolved at the time the URL path [PHP_SELF] = [SCRIPT_NAME] + [PATH_INFO]
is defined, because aliases are considered to search the file system and we know from example 4 in Odin's answer that the file system is searched to determine if the file exists, but this is only relevant when the file is not found. Similarly, mod_dir calls mod_alias to search the file system, but this is only relevant if you have an alias such as Alias \index.php \var\www\index.php
and the request uri is a directory.
Upvotes: 4
Reputation: 3358
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
Upvotes: 259
Reputation: 83981
Personally I use the $REQUEST_URI
as it references the URI entered and not the location on the server's disc.
Upvotes: 4
Reputation: 1943
PATH_INFO
is only available when using htaccess like this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^(favicon\.ico|robots\.txt)
RewriteRule ^(.*)$ index.php/$1 [L]
[SCRIPT_NAME] => /index.php
[PHP_SELF] => /index.php
[PATH_INFO] IS NOT AVAILABLE (fallback to REQUEST_URI in your script)
[REQUEST_URI] => /
[QUERY_STRING] =>
[PHP_SELF] => /index.php/test
[PATH_INFO] => /test
[REQUEST_URI] => /test
[QUERY_STRING] =>
[PHP_SELF] => /index.php/test
[PATH_INFO] => /test
[REQUEST_URI] => /test?123
[QUERY_STRING] => 123
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^(favicon\.ico|robots\.txt)
RewriteRule ^(.*)$ index.php?url=$1 [L,QSA]
[SCRIPT_NAME] => /index.php
[PHP_SELF] => /index.php
[PATH_INFO] IS NOT AVAILABLE (fallback to REQUEST_URI in your script)
[REQUEST_URI] => /
[QUERY_STRING] =>
[REQUEST_URI] => /test
[QUERY_STRING] => url=test
[REQUEST_URI] => /test?123
[QUERY_STRING] => url=test&123
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]
[SCRIPT_NAME] => /index.php
[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
[PHP_SELF] => /index.php/test
[PATH_INFO] => /test
[REQUEST_URI] => /test
[QUERY_STRING] =>
[REDIRECT_LANGUAGE] =>
[PHP_SELF] => /index.php/
[PATH_INFO] => /
[REQUEST_URI] => /en
[QUERY_STRING] =>
[REDIRECT_LANGUAGE] => en
[PHP_SELF] => /index.php/test
[PATH_INFO] => /test
[REQUEST_URI] => /en/test
[REDIRECT_LANGUAGE] => en
[PHP_SELF] => /index.php/test
[PATH_INFO] => /test
[REQUEST_URI] => /en/test?123
[QUERY_STRING] => 123
[REDIRECT_LANGUAGE] => en
Upvotes: 27
Reputation:
Backup a second, you've taken the wrong approach to begin with. Why not just do this
RewriteEngine on
RewriteCond $1 !^(images|inc|favicon\.ico|index\.php|robots\.txt)
RewriteRule ^(.*)$ /index.php?url=$1 [L]
instead? Then grab it with $_GET['url'];
Upvotes: -1
Reputation: 7900
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
Upvotes: 5