PHP_SELF対PATH_INFO対SCRIPT_NAME対REQUEST_URI


105

CodeIgniterでPHPアプリケーションを構築しています。CodeIgniterはすべてのリクエストをメインコントローラに送信します:index.php。ただし、index.phpURI を確認するのは好きではありません。たとえば、http://www.example.com/faq/whateverにルーティングされhttp://www.example.com/index.php/faq/whateverます。スクリプトがそのアドレスが何であるかを知るための信頼できる方法が必要です。そのため、ナビゲーションで何をするかがわかります。mod_rewriteCodeIgniterのドキュメントに従って、私はを使用しました。

ルールは次のとおりです。

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

通常はチェックするだけphp_selfですが、この場合は常にチェックしindex.phpます。、などから入手できますがREQUEST_URIPATH_INFOどちらが最も信頼できるかを判断しようとしています。DOESの誰もが知っている(またはどこ見つけるために知っている)との間に実質的な違いをPHP_SELFPATH_INFOSCRIPT_NAME、とREQUEST_URI?ご協力いただきありがとうございます!

:SOがアンダースコアを認識し、何らかの理由で斜体にするため、スペースを追加する必要がありました。

更新:スペースを修正しました。

回答:


51

PHPのドキュメントには、あなたの違いを見分けることができます。

「PHP_SELF」

ドキュメントルートを基準にした、現在実行中のスクリプトのファイル名。例えば、$ _SERVER [「PHP_SELF」]のアドレスでスクリプト内http://example.com/test.php/foo.barはなり/test.php/foo.bar__FILE__定数には、現在の(つまり含まれている)ファイルの絶対パスとファイル名が含まれます。PHPがコマンドラインプロセッサとして実行されている場合、この変数にはPHP 4.3.0以降のスクリプト名が含まれます。以前は利用できませんでした。

「SCRIPT_NAME」

現在のスクリプトのパスが含まれています。これは、自分自身を指す必要があるページに役立ちます。__FILE__定数には、現在の(つまり含まれている)ファイルの絶対パスとファイル名が含まれます。

「REQUEST_URI」

このページにアクセスするために与えられたURI。たとえば、'/index.html'です。

PATH_INFOが文書化されていないようです...


3
これはおそらくPHPのドキュメントではなくCGIに関するものです:)そしてPATH_INFOがドキュメント化されています:tools.ietf.org/html/rfc3875#section-4しかし、Apacheとnginxがこの変数を常に提供するとは限らないいくつかの既知の問題があります。
SimonSimCity

1
以下のオーディンの答えは、例で補足される有用な説明を追加します。これらの変数が、path_info、クエリ文字列、一部のリダイレクト、一部のエイリアス、CLIとSERVERなどからの一般的なコンテキストで何を表すかを理解するのは難しいと思います

3
-1なぜ私が反対票を投じたのかについての説明と同じように、私がこの投稿に来た全体の理由は、ドキュメントが明確でないためです。以下のオーディンの答えは、これらの変数の違いの明確な説明を提供します。コピーして貼り付けるだけでは不十分で、ドキュメントも不十分であるように感じます。ほとんどの人は、上記の$ _SERVER変数の要素のリストについてさえ知るために、すでにドキュメントにアクセスする必要があったと思います。
ダリン

229

これらの変数の違いのいくつかの実用的な例:
例1. リクエストされたURLが次の形式の場合にのみ、PHP_SELFはSCRIPT_NAMEと異なります:http : //example.com/test.php/foo/bar

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

(これは、PATH_INFOが賢明な情報[PATH_INFO] => / foo / barを含む場合の唯一のケースのようです)注:これは、以前の一部のPHPバージョン(<= 5.0?)では異なっていました。

例2.空でないクエリ文字列が入力されたときのREQUEST_URIはSCRIPT_NAMEとは異なります:http ://example.com/test.php?foo=
bar

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

例3.サーバー側のリダイレクトが有効な場合、REQUEST_URIはSCRIPT_NAMEとは異なります(たとえば、apacheのmod_rewrite)。

http://example.com/test.php

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

例4.スクリプトでHTTPエラーを処理する場合、REQUEST_URIはSCRIPT_NAMEとは異なります。
ApacheディレクティブErrorDocument 404 /404error.php
http://example.com/test.phpの使用

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

カスタムエラーページを使用するIISサーバー上
http://example.com/test.php

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

21
+1、「例は学ぶ方法ではなく、それが学ぶ唯一の方法です。」-私は常にこのことを再確認する必要があります。404エラーに関する非常に素晴らしい調査です。=)
Alix Axel

16
+1:私の人生で初めて違いを理解しました。彼らはあなたの答えでPHPドキュメンテーションを更新する必要があります
Marco Demaio

例1:[SCRIPT_NAME] => /test.php/最後に「/」があってはなりません。いい例です。
Dawid Ohia

あなたは正しいJohnM2です。これでPHP 5.4を確認しました。URL/pinfo.php/first/second?third=fourthの結果は次のとおりです。QUERY_STRING => third = fourth REQUEST_URI => /pinfo.php/first/second ?third = fourth SCRIPT_NAME => /pinfo.php PATH_INFO => / first / second
オーディン

これも5.2.17でテストし/ましたが、の最後にはありませんSCRIPT_NAME。これはPHP 5.2-5.4では一貫しているようで、それを反映するように回答を編集することを検討します。
FABRICIOマット

24

PATH_INFO このようなhtaccessを使用している場合にのみ使用できます。

例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

ルート

http://domain.com/

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

http://domain.com/test

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

クエリ文字列

http://domain.com/test?123

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

例2

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)

ルート

http://domain.com/

[REQUEST_URI]  => /
[QUERY_STRING] => 

http://domain.com/test

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

クエリ文字列

http://domain.com/test?123

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

例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]

または

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

ルート

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

http://domain.com/test

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

言語

http://domain.com/en

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

言語パス

http://domain.com/en/test

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

言語クエリ文字列

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

これは素晴らしかった。ご協力いただきありがとうございます!
ガブリエルフェア

1
この回答は、URLの書き換えのみがpath_infoを作成できることを示唆する方法で記述されていますが、もちろん、パス情報は元のURLに直接入力できます。

12

PHPパス

    $_SERVER['REQUEST_URI']    = Webパス、要求されたURI
    $_SERVER['PHP_SELF']    = Webパス、要求されたファイル+パス情報
    $_SERVER['SCRIPT_NAME']    = Webパス、要求されたファイル
    $_SERVER['SCRIPT_FILENAME']   =ファイルパス、要求されたファイル
    __FILE__    =ファイルパス、現在のファイル

どこ

  • ファイルパスは、エイリアス解決後ののようなシステムファイルパスです/var/www/index.php
  • Webパスはfromの ようなサーバードキュメントパスであり、どのファイルとも一致しない場合があります/index.phphttp://foo.com/index.php
  • 現在のファイルと、含まれているスクリプトファイルではなく、含まれているスクリプトファイルを意味します
  • 要求されたファイルと、インクルードされたファイルではなく、インクルーダスクリプトファイルを意味します
  • URIは、URLを書き換える前ののようなHTTPリクエストです/index.php?foo=bar
  • パス情報は、スクリプト名の後、クエリ文字列の前にある追加のApacheデータです。

操作の順序

  1. クライアントがサーバーにHTTPリクエストを送信する REQUEST_URI
  2. サーバーは、.htaccessファイルなどからURLを書き換えて取得しますPHP_SELF
  3. サーバーが分離PHP_SELFSCRIPT_FILENAME+PATH_INFO
  4. サーバーはエイリアス解決を実行し、取得するURLパス全体をシステムファイルパスに変換しますSCRIPT_FILENAME
  5. 結果のスクリプトファイルには__FILE__、現在のファイルへのパスを参照する他のものが含まれる場合があります

これはいい。これが私のコメントです。まず、$ _ SERVER ['SCRIPT_NAME']と$ _SERVER ['SCRIPT_FILENAME']はどちらもスクリプト名ですが、後者はエイリアスが実行された後です。次に、$ _ SERVER ['PHP_SELF']はスクリプトではなく、スクリプト+パス情報です。繰り返しになりますが、$ _ SERVER ['SCRIPT_NAME']は(エイリアスの前の)スクリプトです。最後に、これらの変数が定義されているのは、書き換えルールの後または前、エイリアスの後または前のどの段階であるかを知っていると便利です。私の答えを見てください。

@ Dominic108私はあなたの提案に基づいて私の回答を修正し、少し整理して、「操作の順序」セクションを追加しました。どう考えているか教えてください。ありがとう!
Beejor 2015

あなたのために、あなたはスワップを持っている$_SERVER['SCRIPT_NAME']と   $_SERVER['PHP_SELF']mod_rewriteのは全体のパスを作成するので、$_SERVER['PHP_SELF']。次に分離が行われます。エイリアスは、スクリプトファイル名を定義するためにパス全体も考慮しますが、script_nameとpath_infoを定義した分離はすでに発生しているため、影響を受けないことに注意してください。

@ Dominic108私はもう一度答えを修正しました。何らかの理由であなたの編集提案が拒否されましたが、私の知る限り、私の2つのアイテムが故障していることは間違いありません。私はエイリアスについてあまり詳しくないので、その部分についてはあなたの専門知識に頼っています。再度、感謝します!
Beejor

5

URIクラスを調べて、$ this-> uri-> uri_string()を利用することができます。

完全なURIを含む文字列を返します。

たとえば、これが完全なURLの場合:

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

関数はこれを返します:

/news/local/345

または、セグメントを使用して、解析/正規表現の値を考え出す必要なく、特定の領域をドリルダウンできます


ありがとう-これは良いアイデアですが、コントローラーを起動して実行する前に実行する必要があるプリシステムフックでこれらを使用しています。
エリ

4

個人的には、$REQUEST_URIサーバーのディスク上の場所ではなく、入力されたURIを参照するために使用します。


常に完全なURIですか?
Eli

通常、Windowsのapacheで問題が発生する可能性がありますが、解決されないのはURIのみです。
Xenph Yan

4

オーディンの答えに追加することはほとんどありません。URLの書き換えとエイリアスの影響を示すために、HTTPリクエストからファイルシステム上の実際のファイルへの完全な例を提供したいと思いました。ファイルシステムでは、スクリプト/var/www/test/php/script.php

<?php
include ("script_included.php")
?>

どこ/var/www/test/php/script_included.php

<?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>";  
?>

そして、 /var/www/test/.htaccess あります

RewriteEngine On
RewriteRule before_rewrite/script.php/path/(.*) after_rewrite/script.php/path/$1 

Apache構成ファイルにはエイリアスが含まれています

Alias /test/after_rewrite/ /var/www/test/php/

そしてhttpリクエストは

www.example.com/test/before_rewrite/script.php/path/info?q=helloword

出力は

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

以下は常に成り立つ

PHP_SELF = SCRIPT_NAME + PATH_INFO = full url path between domain and query string. 

mod_rewrite、mod_dir、ErrorDocument rewrite、または任意の形式のURL書き換えがない場合は、

REQUEST_URI = PHP_SELF + ? + QUERY_STRING 

エイリアスは、システムファイルパスに影響SCRIPT_FILENAMEし、__FILE__下記の例外を参照してください-ではなく、前に定義されているURLのパスを、。エイリアスは、を含むURLパス全体を使用する場合がありますPATH_INFO。間にまったく接続があってできなかったSCRIPT_NAMESCRIPT_FILENAME

[PHP_SELF] = [SCRIPT_NAME] + [PATH_INFO] エイリアスはファイルシステムを検索すると見なされ、ファイルシステムがファイルの存在を確認するために検索されることがオーディンの回答の例4からわかっているため、URLパスの定義時にエイリアスが解決されないことは完全に正確ではありません。しかし、これはファイルが見つからない場合にのみ関係します。同様に、mod_dirはmod_aliasを呼び出してファイルシステムを検索しますが、これは、などのエイリアスがAlias \index.php \var\www\index.phpあり、リクエストuriがディレクトリである場合にのみ関係します。


こんにちはDominic108、改訂をありがとう。書き換え情報を含めると便利だと思います。私にはそれが暗示されていましたが、他の人にはそれは直感的ではないかもしれません。
Beejor 2015

1

どの変数が何をするかを忘れた場合は、phpinfo()を使用する小さなスクリプトを記述し、クエリ文字列を使用してURLから呼び出すことができます。サーバーソフトウェアのインストールはPHPが返す変数を提示するため、サーバーの構成ファイルでの書き換えが予期したものとは異なる結果を引き起こしている場合に備えて、マシンの出力を確認することを常にお勧めします。次のように保存します_inf0.php

<?php
    $my_ip = '0.0.0.0';

   if($_SERVER['REMOTE_ADDR']==$my_ip){
     phpinfo();
   } else {
     //something
   }

それからあなたは電話します /_inf0.php?q=500


-1

1秒バックアップしてください。最初は間違ったアプローチをとっています。なぜこれをしないのですか

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

代わりに?次にそれをつかみます$_GET['url'];


なぜ車輪を再発明するのですか?このデータへのアクセスははるかに簡単です!
ケネス

また、元のリクエストにクエリ文字列が含まれることが予想される場合は、さらに複雑になります。現在の状態では、上記のコードはクエリ文字列を上書きするだけです。クエリ文字列(QSAフラグ)をマージすると、クエリ文字列のパラメーターが上書きされる可能性があり(たとえば、url最初のリクエストでパラメーターが必要になった場合)、さらに悪いことに、XSS攻撃に対して脆弱になる可能性があります。
MrWhite
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.