深入理解PHP之require/include順序 推薦
也就有了如下的疑問(wèn):
include_path是怎么起作用的?
如果有多個(gè)include_path順序是怎么樣的?
什么情況下include_path不起作用?
今天, 我就全面的介紹下這個(gè)問(wèn)題, 先從一個(gè)例子開(kāi)始吧.
如下的目錄結(jié)構(gòu):
- 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”;
現(xiàn)在, 我的問(wèn)題來(lái)了:
1. 當(dāng)在root目錄下運(yùn)行1.php, 會(huì)得到什么輸出?
2. 在subdir下運(yùn)行上一級(jí)目錄的1.php, 有會(huì)得到什么輸出?
3. 當(dāng)取消include_path中的當(dāng)前目錄path(也就是include_path=”path_to_subdir”), 上面?zhèn)z個(gè)問(wèn)題又會(huì)是什么輸出?
PHP中的include_path
PHP在遇到require(_once)/include(_once)的指令的時(shí)候, 首先會(huì)做如下的判斷:
要包含的文件路徑是絕對(duì)路徑么?
如果是, 則直接包含, 并結(jié)束.
如果不是, 進(jìn)入另外的邏輯(經(jīng)過(guò)多次調(diào)用, 宏展開(kāi)后進(jìn)入_php_stream_fopen_with_path)尋找此文件
接下來(lái), 在_php_stream_fopen_with_path中, 會(huì)做如下判斷:
要包含的文件路徑是相對(duì)路徑么(形如./file, ../dir/file, 以下用"目錄相對(duì)路徑代替")?
如果是, 則跳過(guò)include_path的作用邏輯, 直接解析相對(duì)路徑(隨后單獨(dú)介紹)
會(huì)根據(jù)include_path,和當(dāng)前執(zhí)行文件的path組成一個(gè)待選的目錄列表, 比如對(duì)于文章前面的例子來(lái)說(shuō), 會(huì)形成一個(gè)如下的待選列表
".:path_to_subdir:current_script_dir
然后, 依次從待選列表頭部開(kāi)始, 根據(jù)DEFAULT_DIR_SEPARATOR(本文的環(huán)境是”:”)取出待選列表中的一個(gè)路徑, 然后把要包含的文件名附加在這個(gè)路徑后面, 進(jìn)行嘗試. 如果成功包含, 則返回, 否則繼續(xù)下一個(gè)待選路徑.
到現(xiàn)在為止, 我們已經(jīng)可以回答我開(kāi)頭提出的3個(gè)問(wèn)題了.
1. 因?yàn)樵趓oot目錄下執(zhí)行, 所以在1.php中包含2.php的時(shí)候, include_path的第二個(gè)待選路徑起了作用(path_to_subdir), 找到了path_to_subdir/2.php, 而在2.php包含3.php的時(shí)候, 當(dāng)前工作目錄是root下, 所以在包含3.php的時(shí)候, include_path的第一個(gè)待選路徑”.”(當(dāng)前工作目錄)下就找到的匹配的文件, 所以得到的輸出是”root”.
2. 同1, 只不過(guò)當(dāng)前的路徑是subdir, 所以得到的輸出是”subdir”.
3. 因?yàn)闆](méi)有了當(dāng)前路徑為include_path, 所以在root目錄下運(yùn)行的時(shí)候2.php中包含3.php的時(shí)候, 是path_to_subdir起了作用, 所以無(wú)論在root還是subdir都將得到”subdir”的輸出.
而如果在2.php中清空include_path,
<?php
ini_set("include_path", '');
require("3.php");
?>
那么將會(huì)是current_script_dir起作用, 而這個(gè)時(shí)候current_script_dir是2.php的路徑, 所以還是會(huì)得到”subdir”的輸出.
目錄相對(duì)路徑
在使用目錄相對(duì)路徑的情況下, 相對(duì)路徑的基點(diǎn), 永遠(yuǎn)都是當(dāng)前工作目錄.
為了說(shuō)明在目錄相對(duì)路徑下的情況,我們?cè)倏磦€(gè)列子, 還是上面的目錄結(jié)構(gòu), 只不過(guò)1.php變成了:
<?php
ini_set("include_path", "/");
require("./subdir/2.php");
?>
2.php變成了:
<?php
require("./3.php");
?>
如果在root目錄下執(zhí)行, 2.php中尋找3.php將會(huì)在當(dāng)前目錄的相對(duì)路徑下尋找, 所以得到的輸出是”root”, 而如果是在subdir下執(zhí)行上一級(jí)目錄的1.php(php -f ../1.php), 將會(huì)因?yàn)樵趕ubdir下找不到”./subdir/2.php”而異常退出.
后記
1. 因?yàn)槭褂胕nclude_path和相對(duì)路徑的情況下, 性能會(huì)和尋找的次數(shù)有關(guān), 最壞的情況下, 如果你有10個(gè)include_path, 那么最多可能會(huì)重試11次才能找到要包含的文件, 所以, 在能使用絕對(duì)路徑的情況下最好使用絕對(duì)路徑.
2. 因?yàn)槟夸浵鄬?duì)路徑的basedir, 永遠(yuǎn)都是當(dāng)前工作路徑, 如果要使用, 需要和實(shí)際部署路徑相關(guān), 所以實(shí)際使用的很少(當(dāng)然, 也有借助chdir來(lái)完成的模塊).
3. 在模塊化的系統(tǒng)設(shè)計(jì)中, 一般應(yīng)該在模塊內(nèi), 通過(guò)獲取模塊的部署路徑(dirname(__FILE__), php5.3以后更是提供了__DIR__常量)從而使用絕對(duì)路徑.
相關(guān)文章
PHP+MySql+jQuery實(shí)現(xiàn)的"頂"和"踩"投票功能
這篇文章主要為大家詳細(xì)介紹了PHP+MySql+jQuery實(shí)現(xiàn)的"頂"和"踩"投票功能,具有一定的參考價(jià)值,感興趣的朋友可以參考一下2016-05-05php + nginx項(xiàng)目中的權(quán)限詳解
這篇文章主要給大家介紹了關(guān)于php + nginx項(xiàng)目中權(quán)限的相關(guān)資料,文章介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-05-05完美實(shí)現(xiàn)GIF動(dòng)畫(huà)縮略圖的php代碼
縮略圖是個(gè)很常用的功能。它的實(shí)現(xiàn)并不復(fù)雜,但如果原圖是GIF動(dòng)畫(huà)的話,問(wèn)題就會(huì)變得繁瑣一點(diǎn)。2011-01-01PHP CURL post數(shù)據(jù)報(bào)錯(cuò) failed creating formpost data
我們有時(shí)候用curl上傳文件遇到failed creating formpost data的錯(cuò)誤,那具體是如何產(chǎn)生,又如何進(jìn)行處理解決呢,下面我們就來(lái)探討下2016-10-10PHP 冒泡排序 二分查找 順序查找 二維數(shù)組排序算法函數(shù)的詳解
本篇文章是對(duì)PHP 冒泡排序 二分查找 順序查找 二維數(shù)組排序算法函數(shù)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06PHP htmlspecialchars_decode()函數(shù)用法講解
今天小編就為大家分享一篇關(guān)于PHP htmlspecialchars_decode()函數(shù)用法講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03PHP設(shè)置一邊執(zhí)行一邊輸出結(jié)果的代碼
這篇文章主要介紹了PHP中設(shè)置一邊執(zhí)行一邊輸出結(jié)果的實(shí)現(xiàn)代碼,需要的朋友可以參考下2013-09-09