如題,只做個記錄下php中的路徑包含的未定式:
被PHP的include路徑弄暈了。自己實驗一通,總結如下。
定義A=包含檔案 B=被A包含的檔案 C=被B包含的檔案
也就是說 A 包含 B, B包含C
A中有
Php代碼
- require '[B路徑]' //(這裡的require可以換成require_once include)
require '[B路徑]' //(這裡的require可以換成require_once include)
B中有
Php代碼
- require '[C路徑]' //(這裡的require可以換成require_once include)
require '[C路徑]' //(這裡的require可以換成require_once include)
下面的討論主要針對A為入口檔案,即只直接存取A,不直接存取B。
首先定義兩個概念:相對路徑和全路徑,我對它們的定義是,相對路徑指以.開頭的路徑,例如
./a/a.php (相對目前的目錄)
../common.inc.php (相對上級目錄), 全路徑是以/開頭或者windows下的C:/類似的盤符開頭的路徑,全路徑不用任何參考路徑就可以唯一確定檔案的最終地址。 例如
/apache/wwwroot/site/a/a.php
c:/wwwroot/site/a/a.php
除了相對路徑和全路徑之外的路徑還有其他類型的路徑嗎? 還有。凡是不以.或者/開頭、也不是windows下盤符:/開頭的路徑,例如
a/a.php common.inc.php,這樣的路徑,就是第三種類型路徑。開始以為這也是相對路徑,但在php的include/require包含機制中,這種類型的路徑跟以.開頭的相對路徑處理是完全不同的。 (require './a.php' 和 require 'a.php' 是不同的!)我們姑且叫這種路徑為未確定路徑
下面分析這三種類型包含路徑的處理方式:首先記住一個結論:如果包含路徑為相對路徑或者全路徑,則不會到include_path中去尋找該檔案,也就是說不管php.ini中定義的include_path環境變數是多少,或者在程式中設定set_include_path(...)為多少。
引用If a path is defined (full or relative), the include_path will be ignored altogether.
注意:下面的討論和結論基於這樣的環境:
假設 A=[SITE]/app/test/main.php,再次強調下面的討論是針對直接存取A的情況。 ([SITE]代表網站的根目錄,可以替換成成http://www.xxx.com這樣的網域名稱根路徑或者文檔儲存的物理目錄如: c:/wwwroot/xxx.com 或者 /usr/wwwroot/xxx.com ),請讀者在自己能測試的網站根目錄建立/app/test/
目錄,並在其中建立main.php,最好是把下面的例子都實踐一下。
1. 相對路徑:
相對路徑需要一個參考目錄才能確定檔案的最終路徑,在包含解析中,這個參考目錄是程式執行入口檔案所在目錄,不管包含嵌套多少層。
如果
A中定義 require './b/b.php'; //則B=[SITE]/app/test/b/b.php
B中定義 require './c.php'; //則C=[SITE]/app/test/c.php 不是
[SITE]/app/test/b/c.php
如果
A中定義 require './b/b.php'; //則B=[SITE]/app/test/b/b.php
B中定義 require '../c.php'; //則C=[SITE]/app/c.php 不是
[SITE]/app/test/c.php
如果
A中定義 require '../b.php'; //則B=[SITE]/app/b.php
B中定義 require '../c.php'; //則C=[SITE]/app/c.php 不是
[SITE]/c.php
如果
A中定義 require '../b.php'; //則B=[SITE]/app/b.php
B中定義 require './c/c.php'; //則C=[SITE]/app/test/c/c.php 不是
[SITE]/app/c/c.php
如果
A中定義 require '../inc/b.php'; //則B=[SITE]/app/inc/b.php
B中定義 require './c/c.php'; //則C還是=[SITE]/app/test/c/c.php 不是
[SITE]/app/inc/c/c.php
同理如果
A中定義 require '../inc/b.php'; //則B=[SITE]/app/inc/b.php
B中定義 require './c.php'; //則C=[SITE]/app/test/c.php 不是
[SITE]/app/inc/c.php
2. 全路徑:
全路徑的比較簡單,不容易混淆出錯。舉一個簡單例子
A中定義 require '/wwwroot/xxx.com/app/test/b.php'; //則在windows下B=c:/wwwroot/xxx.com/app/test/b.php
(c:為伺服器所在盤符),在linux下B=/wwwroot/xxx.com/app/test/b.php
dirname(__FILE__)計算出來的也是一個全路徑形式的目錄,但是要注意__FILE__是一個Magic constants,不管在什麼時候都等於寫這條語句的php檔案所在的全路徑,因此dirname(__FILE__)也總是指向寫這條語句的php檔案所在的全路徑,跟這個檔案是否被其他檔案包含使用沒有任何關係。
例如:
A中定義 require '../b.php'; //則B=[SITE]/app/b.php
B中定義 require dirname(__FILE__).'/c.php'; //則B=[SITE]/app/c.php
如果
A中定義 require '../inc/b.php'; //則B=[SITE]/app/inc/b.php
B中定義 require dirname(__FILE__).'/c.php'; //則B=[SITE]/app/inc/c.php 始終跟B在同一個目錄
結論:不管B是被A包含使用,還是直接被訪問,
B如果 require dirname(__FILE__).'/c.php' ,則始終引用到跟B在同一個目錄中的 c.php檔案;
B如果 require dirname(__FILE__).'/../c.php' ,則始終引用到B檔案所在目錄的父目錄中的 c.php檔案;
B如果 require dirname(__FILE__).'/c/c.php' ,則始終引用到B檔案所在目錄的c子目錄中的 c.php檔案;
3. 除相對路徑和全路徑之外的未確定路徑
首先在逐一用include_path中定義的包含目錄來拼接[未確定路徑],找到存在的檔案則包含成功退出,如果沒有找到,則用寫require語句的php檔案所在目錄來拼接[未確定路徑]組成的全路徑去尋找該檔案,如果檔案存在則包含成功退出,否則表示包含檔案不存在,出錯。
下面的討論和結論需要首先在A檔案的開頭調用 set_include_path(dirname(__FILE__).'/../inc'); 設定include_path為
[SITE]/app/test/../inc 目錄,其實就是
[SITE]/app/inc
並且在A中定義 require '../b.php'; //把B固定在[SITE]/app/b.php
這樣如果
引用自:http://cuckoosnest.iteye.com/blog/479401