2013-07-07 79 views
2

我有一個應該安裝在不同服務器上的PHP項目。 它在項目根目錄中有一個名爲includes.php的包含文件,可以從整個項目中的多個位置調用,例如文件file1.php(位於includes.php的相同位置),subdir/file2.phpsubdir2/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; 
} 
+0

這個「return-the-project-root-url」函數將被放置的文件是否與項目根有已知關係?還是你有前端控制器(每個請求發送的文件)? – complex857

+0

是的,includes.php位於項目根目錄下。不,我沒有前端控制器。 – LeRainieur

回答

2

我想要類似的東西。但是想要省略文件名稱。

我希望這有助於隊友!

RAW處理方法:
這花了一段時間來完善,而我一直在爲其中不要求變量人或項目的例子。對於你的情況,你可以成爲一個全球性的。

$current_url = (empty($_SERVER['HTTPS']) ? "http://" : "https://") . ($_SERVER['SERVER_NAME']) . (((empty($_SERVER['HTTPS']) ? 'http' : 'https') == "http" && $_SERVER['SERVER_PORT'] == 80 || (empty($_SERVER['HTTPS']) ? 'http' : 'https') == "https" && $_SERVER['SERVER_PORT'] == 443) ? "" : ":" . $_SERVER['SERVER_PORT']) . (preg_replace("!^". preg_replace("!". $_SERVER['SCRIPT_NAME'] ."$!", "", $_SERVER['SCRIPT_FILENAME']) ."!", "", __DIR__)); 


OR,更簡單的方法:)

$protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://"; 
$path = substr(dirname(__FILE__), strlen($_SERVER['DOCUMENT_ROOT'])); 
$current_url = $protocol . $_SERVER['HTTP_HOST'] . $path; 


示例輸出:(HTTPS,HTTP,端口等)

https://example.xyz/base/path/without/file/ 
    http://another.example.com/uploads/test/ 
    http://www.return.url:81/blah/blahblah/example/