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_URI, PATH_INFO등,하지만 난 가장 신뢰할 수있을 것입니다 결정하기 위해 노력하고있어. 사람의 노하우를합니까 (또는 어디에서 찾을 알고) 사이의 진정한 차이 PHP_SELF, PATH_INFO, SCRIPT_NAME,와 REQUEST_URI? 당신의 도움을 주셔서 감사합니다!

참고 : 나는 밑줄이 보이기 때문에 공백을 추가해야했으며 어떤 이유로 든 기울임 꼴로 만듭니다.

업데이트 됨 : 공백을 수정했습니다.

답변:


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 2012

1
아래 Odin의 답변은 예제로 보완되는 유용한 설명을 추가합니다. 나는 그것이 어려운 이러한 변수 등, CLI에서 서버 대, 서로 다른 운영 체제에서하는 PATH_INFO, 쿼리 문자열, 일부 리디렉션, 일부 별명을 가진 일반적인 맥락에서 표현을 이해하기 위해 찾을

3
-1 내가 반대표를 던진 이유에 대한 설명처럼 : 내가이 게시물에 온 이유는 문서가 명확하지 않기 때문입니다. 아래 Odin의 답변은 이러한 변수 간의 차이점에 대한 명확한 설명을 제공합니다. 쉽게 찾을 수있는 복사와 붙여 넣기에 대한 답은 충분하지 않지만 문서도 부족한 것 같습니다. 나는 대부분의 사람들이 위에서 언급 한 $ _SERVER 변수의 요소 목록에 대해 알기 위해 이미 문서를 방문해야한다고 생각합니다.
dallin

229

이러한 변수 간의 차이점에 대한 몇 가지 실제 예 :
예 1. PHP_SELF는 요청 된 URL이 http://example.com/test.php/foo/bar 형식 일 때만 SCRIPT_NAME과 다릅니다
.

[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과 다릅니다 (예 : 아파치의 mod_rewrite).

http://example.com/test.php

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

예 4. REQUEST_URI는 스크립트로 HTTP 오류를 처리 할 때 SCRIPT_NAME과 다릅니다.
Apache 지시문 사용 ErrorDocument 404 /404error.php
http://example.com/test.php

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

사용자 지정 오류 페이지 http://example.com/test.php를 사용하는 IIS 서버에서

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

21
+1, "예는 배우는 방법이 아니라 배우는 유일한 방법입니다." -저는 항상이 물건을 다시 확인해야합니다. 404 오류에 대한 아주 좋은 연구입니다. =)
Alix Axel

16
+1 : 내 인생에서 처음으로 차이를 이해했습니다. 그들은 당신의 답변으로 PHP 문서를 업데이트해야합니다
Marco Demaio 2011 년

예제 1 : [SCRIPT_NAME] => /test.php/ 끝에 "/"가 없어야합니다. 예제 1 : [SCRIPT_NAME] => /test.php 어쨌든 PHP 5.3.6에서 볼 수 있습니다. 좋은 예.
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
Odin

나는 이것을 5.2.17에서도 테스트 /했으며 SCRIPT_NAME. 이것은 PHP 5.2-5.4에서 일관된 것처럼 보입니다. 답을 수정하여 그것을 반영하는 것을 고려하십시오.
Fabrício Matté 2012 년

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

이것은 훌륭했습니다. 당신의 도움을 주셔서 감사합니다!
Gabriel Fair

1
이 답변은 URL 재 작성 만 path_info를 만들 수 있지만 경로 정보는 원래 URL에 직접 입력 할 수 있음을 암시하는 방식으로 작성되었습니다.

12

PHP 경로

    $_SERVER['REQUEST_URI']    = 웹 경로, 요청 된 URI
    $_SERVER['PHP_SELF']    = 웹 경로, 요청 된 파일 + 경로 정보
    $_SERVER['SCRIPT_NAME']    = 웹 경로, 요청 된 파일
    $_SERVER['SCRIPT_FILENAME']   = 파일 경로, 요청 된 파일
    __FILE__    = 파일 경로, 현재 파일

어디

  • 파일 경로 는 별칭 확인 후 와 같은 시스템 파일 경로입니다./var/www/index.php
  • 웹 경로 는 from 과 같은 서버 문서 경로 이며 어떤 파일과도 일치하지 않을 수 있습니다./index.phphttp://foo.com/index.php
  • 현재 파일 은 포함 된 스크립트 파일을 의미 하며이를 포함 하는 스크립트가 아닙니다.
  • 요청 된 파일 은 포함 된 스크립트 파일 이 아니라 includer 스크립트 파일을 의미 합니다.
  • 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

mod_rewrite가 전체 경로를 생성하기 때문에 주문에 따라 $_SERVER['SCRIPT_NAME']및   을 교체해야합니다 . 다음에 분리가 발생합니다. 별칭은 스크립트 파일 이름을 정의하기 위해 전체 경로도 고려하지만 script_name 및 path_info를 정의한 구분이 이미 발생 했으므로 영향을받지 않습니다. $_SERVER['PHP_SELF']$_SERVER['PHP_SELF']

@ Dominic108 나는 내 대답을 다시 수정했습니다. 내가 아는 한, 내 항목 중 두 개가 고장났다는 것이 맞습니다. 나는 별칭에 익숙하지 않으므로 해당 부분에 대한 귀하의 전문 지식에 의존하고 있습니다. 다시 한 번 감사드립니다!
Beejor

5

URI 클래스 를 살펴보고 $ this-> uri-> uri_string ()을 사용할 수 있습니다.

전체 URI가있는 문자열을 반환합니다.

예를 들어 이것이 귀하의 전체 URL 인 경우 :

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

이 함수는 다음을 반환합니다.

/news/local/345

또는 구문 분석 / 정규식 값을 제시하지 않고도 세그먼트를 사용하여 특정 영역을 드릴 다운 할 수 있습니다.


감사합니다-이것은 좋은 생각이지만 컨트롤러가 실행되기 전에 실행해야하는 사전 시스템 후크에서 사용하고 있습니다.
Eli

4

개인적으로 $REQUEST_URI서버 디스크의 위치가 아닌 입력 된 URI를 참조하므로를 사용합니다 .


항상 완전한 URI입니까?
Eli

일반적으로 Windows에서 아파치 문제가 발생할 수 있지만 해결되지 않는 URI에만 해당됩니다.
Xenph Yan

4

Odin의 대답에 추가 할 것이 거의 없습니다. 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 재 작성 또는 URL 재 작성 형식이없는 경우

REQUEST_URI = PHP_SELF + ? + QUERY_STRING 

별명은 시스템 파일 경로에 영향을 SCRIPT_FILENAME하고 __FILE__아래 예외를 참조 -이 아니라 이전에 정의 된 URL 경로를. 별칭은를 포함하여 전체 URL 경로를 사용할 수 있습니다 PATH_INFO. SCRIPT_NAME와 사이에 전혀 연결이 없을 수 있습니다 SCRIPT_FILENAME.

별칭이 [PHP_SELF] = [SCRIPT_NAME] + [PATH_INFO] 파일 시스템을 검색하는 것으로 간주되고 Odin의 답변에서 예 4에서 파일이 존재하는지 확인하기 위해 파일 시스템이 검색된다는 것을 알고 있기 때문에 URL 경로 가 정의 될 때 별칭이 확인되지 않는다는 것은 완전히 정확하지 않습니다 . 그러나 이것은 파일을 찾을 수없는 경우에만 관련됩니다. 마찬가지로, mod_dir은 mod_alias를 호출하여 파일 시스템을 검색하지만 이는 같은 별칭이 Alias \index.php \var\www\index.php있고 요청 uri가 디렉토리 인 경우에만 관련이 있습니다 .


안녕하세요 Dominic108, 수정 해 주셔서 감사합니다. 재 작성 정보를 포함하는 것이 유용하다고 생각합니다. 나에게는 암시 적이지만 다른 사람들에게는 그렇게 직관적이지 않을 수 있습니다.
Beejor

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

잠시 백업하세요. 처음부터 잘못된 접근 방식을 취했습니다. 왜 그냥하지

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

대신? 그런 다음$_GET['url'];


바퀴를 재발 명하는 이유는 무엇입니까? 이 데이터는 훨씬 더 쉽게 액세스됩니다!
Kenneth

원래 요청에 쿼리 문자열이있을 것으로 예상되는 경우 추가 복잡성이 있습니다. 현재 상태에서 위 코드는 단순히 쿼리 문자열을 덮어 씁니다. 쿼리 문자열 ( QSA플래그)을 병합하면 쿼리 문자열 매개 변수를 잠재적으로 덮어 쓰거나 (예 : url초기 요청에 매개 변수가 필요한 경우 ), 더 나쁜 경우 XSS 공격에 취약해질 수 있습니다.
MrWhite
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.