我有一個應該安裝在不同服務器上的PHP項目。 它在項目根目錄中有一個名爲includes.php
的包含文件,可以從整個項目中的多個位置調用,例如文件file1.php
(位於includes.php
的相同位置),subdir/file2.php
和subdir2/file3.php
。包含文件包含一個函數,該函數應該返回整個項目的絕對URL,例如http://www.myserver.com/myproject/
,無論函數調用哪個文件。PHP:查找項目根目錄的絕對URL
- 我不能使用
$_SERVER["REQUEST_URI"]
,因爲它會返回調用該函數的文件的URL(它會變化)。我不想傳遞一個表示「上移兩個目錄」或類似的參數,因爲這個URL函數可以被調用的地方有很多地方。 - 我不能使用
__FILE__
和$_SERVER['DOCUMENT_ROOT']
(這是一些推薦的),因爲我們的服務器有一些奇怪的配置,使得__FILE__
不在$_SERVER['DOCUMENT_ROOT']
的子目錄中。 (我寫我的學校的項目,但它應該被分配到其他學校。)
我最後的解決辦法是採取$_SERVER["REQUEST_URI"]
,刪除文件的一部分,並使用get_headers()
來檢查是否有已知的文件( dummy.php
)可以在這個目錄中找到。如果沒有,我檢查父目錄等等。不幸的是,get_headers()
不會在我們的學校服務器上返回任何東西(儘管它在我家的測試系統上工作)。
有效的解決方案(但我不太喜歡)是將項目根URL包含在配置文件中。
有沒有人有另一個想法呢?提前致謝!
編輯: 好吧,我找到了一個適合我的解決方案。我仍然樂於評論如何做得更好,也許沒有使用debug_backtrace()
?有沒有理由不使用這個功能?
function urlPath()
{
$trace = debug_backtrace();
$first_frame = $trace[count($trace)-1];
// the lowest frame gives us the filename from which the first call was made
$callerdir = dirname($first_frame['file']);
$includedir = dirname(__FILE__);
$rootLength = strlen($includedir);
$subDir = substr($callerdir, $rootLength);
$subdirDepth = substr_count($subDir,DIRECTORY_SEPARATOR);
// I use the fact that the include file is in the project root folder, so its
// folder path must be a prefix of any other file's folder path. I remove this
// prefix and count the number of path separators to get the "relative depth".
$pageURL = 'http';
if (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on")
{
$pageURL .= "s";
}
$pageURL .= "://" . $_SERVER["SERVER_NAME"];
if (isset($_SERVER["SERVER_PORT"]) && $_SERVER["SERVER_PORT"] != "80")
{
$pageURL .= ":".$_SERVER["SERVER_PORT"];
}
$pageURL .= $_SERVER["REQUEST_URI"];
// I get the absolute URL of the calling page
for ($i = 0; $i <= $subdirDepth; $i++)
{
$idx = strrpos($pageURL,'/');
$pageURL = substr($pageURL, 0, $idx);
}
// I remove the required number of subdirectories plus one for the filename
return $pageURL;
}
這個「return-the-project-root-url」函數將被放置的文件是否與項目根有已知關係?還是你有前端控制器(每個請求發送的文件)? – complex857
是的,includes.php位於項目根目錄下。不,我沒有前端控制器。 – LeRainieur