PHP require與include順序的詳解

黄舟
發布: 2023-03-11 11:58:01
原創
1183 人瀏覽過

在大型的Web專案中, include_path是一個模組化設計的根本中的根本(當然,現在也有很多基於autoload的設計, 這個不影響本文的探討), 但正是因為include_path, 常常會讓我們遇到一些因為沒有找到正確的文件而導致的看似」詭異」的問題.

也就有瞭如下的疑問:

include_path是怎麼運作的?

如果有多個include_path順序是怎麼樣的?

什麼情況下include_path不起作用?

#今天, 我就全面的介紹下這個問題, 先從一個例子開始吧.

如下的目錄結構:

  root    
  ├ 1.php    
  ├ 3.php    
  └ subdir         
  ├ 2.php          
  └ 3.php
登入後複製

在1.php中:

 程式碼如下:

<?php 
ini_set("include_path", ".:path_to_subdir"); 
require
("2.php"); 
?>
登入後複製


而在2.php中:

<?php 
require("3.php"); 
?>
登入後複製

而在root目錄下的3.php列印出」root ”, 在subdir目錄下的3.php打印出”subdir”;

現在, 我的問題來了:
1. 當在root目錄下運行1.php, 會得到什麼輸出?
2. 在subdir下運行上一級目錄的1.php, 有會得到什麼輸出?
3. 當取消include_path中的當前目錄path(也就是include_path=”path_to_subdir”),上面兩個問題又會是什麼輸出?
PHP中的include_path
PHP在遇到require(_once)/include(_once)的指令的時候, 首先會做如下的判斷: 要包含的檔案路徑是絕對路徑麼? 

如果是, 則直接包含, 並結束.
如果不是, 進入另外的邏輯(經過多次呼叫, 巨集展開後進入_php_stream_fopen_with_path)尋找此檔案


接下來, 在_php_stream_fopen_with_path, 會做以下判斷: 

要包含的檔案路徑是相對路徑麼(形如./file, ../dir/file, 以下以"目錄相對路徑代替")?
如果是, 則跳過include_path的作用邏輯, 直接解析相對路徑(隨後單獨介紹)


會根據include_path,和目前執行檔的path組成一個待選的目錄列表, 例如對於文章前面的例子來說, 會形成一個如下的待選列表

 代碼如下:

".:path_to_subdir:current_script_dir
登入後複製

然後, 依次從待選列表頭部開始, 根據DEFAULT_DIR_SEPARATOR(本文的環境是”:”)取出待選列表中的一個路徑, 然後把要包含的文件名附加在這個路徑後面,進行嘗試. 如果成功包含, 則返回, 否則繼續下一個待選路徑.
到現在為止, 我們已經可以回答我開頭提出的3個問題了.
1. 因為在root目錄下執行,所以在1.php包含2.php的時候, include_path的第二個待選路徑起了作用(path_to_subdir), 找到了path_to_subdir/2.php, 而在2.php包含3.php的時候, 目前工作目錄是root下, 所以在包含3.php的時候, include_path的第一個待選路徑”.”(當前工作目錄)下就找到的匹配的文件, 所以得到的輸出是”root”.
2. 同1, 只不過當前的路徑是subdir, 所以得到的輸出是”subdir”.
3. 因為沒有了當前路徑為include_path, 所以在root目錄下運行的時候2.php包含3. php的時候, 是path_to_subdir起了作用, 所以無論在root還是subdir都將得到”subdir”的輸出.
而如果在2.php中清空include_path,

#
<?php 
ini_set("include_path", &#39;&#39;); 
require("3.php"); 
?>
登入後複製


#那麼將會是current_script_dir起作用, 而這個時候current_script_dir是2.php的路徑, 所以還是會得到”subdir”的輸出.
目錄相對路徑
#在使用目錄相對路徑的情況下, 相對路徑的基點, 永遠都是當前工作目錄.
為了說明在目錄相對路徑下的情況,我們再看個列子, 還是上面的目錄結構, 只不過1.php變成了:

<?php 
ini_set("include_path", "/"); 
require("./subdir/2.php"); ?>
登入後複製


2.php變成了: 

<?php 
require("./3.php"); 
?>
登入後複製


如果在root目錄下執行, 2.php中尋找3.php將會在目前目錄的相對路徑下尋找, 所以得到的輸出是”root”, 而如果是在subdir下執行上一級目錄的1.php(php -f ../1.php), 將會因為在subdir下找不到”./subdir/2.php”而異常退出.
後記
#1. 因為使用include_path和相對路徑的情況下, 性能會和尋找的次數有關, 最壞的情況下, 如果你有10個include_path, 那麼最多可能會重試11次才能找到要包含的檔案, 所以, 在能使用絕對路徑的情況下最好使用絕對路徑.
2. 因為目錄相對路徑的basedir, 永遠都是當前工作路徑, 如果要使用, 需要和實際部署路徑相關, 所以實際使用的很少(當然, 也有藉助chdir來完成的模組).
3. 在模組化的系統設計中, 一般應該在模組內, 通過獲取模組的部署路徑(dirname(FILE), php5.3以後更是提供了DIR常數)從而使用絕對路徑.

以上是PHP require與include順序的詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!