2011-07-24 62 views
4

是否有PHP內部函數用於路徑連接?我有什麼可能合併幾條路徑(絕對和相對)。PHP連接的路徑

//Example: 
$path1="/usr/home/username/www"; 
$path2="domainname"; 
$path3="images/thumbnails"; 
$domain="exampledomain.com"; 

//As example: Now I want to create a new path (domain + path3) on the fly. 
$result = $domain.DIRECTORY_SEPARATOR.$path3 

好,對於這個例子簡單的解決方案,但如果有不同的字典分離器或一些路徑是有點複雜?

有一個現有的解決方案,修剪它是這樣的:/home/uploads/../uploads/tmp => /家/上傳/ tmp目錄....

?如何獨立於平臺的版本一個路徑連接函數的外觀如何?

相對路徑應該以「./」作爲前綴開始,還是以「home/path/img /」爲常用方式?

回答

5

我碰到這個問題我自己,主要是關於路徑正常化

規範化是:

  • 一個分離器(我選擇了支持,但永遠不會返回向後斜線\\
  • 解決間接:/../
  • 刪除重複分隔符:/home/www/uploads//file.ext
  • 始終刪除尾隨分隔符。

我已經寫了一個實現這個功能。我目前無法訪問該代碼,但自己編寫代碼也並不難。

對於這個規範化函數的實現,路徑是否是絕對的並不重要,只要注意領先的分隔符並且你很好。

我並不太擔心操作系統的依賴。 Windows和Linux PHP都明白/,所以爲了簡單起見,我只是總是使用它 - 但我想這與你使用的分隔符無關。


要回答你的問題:路徑的級聯可以很容易的,如果你只是總是使用/假設一個目錄沒有尾隨分隔符。 '沒有尾隨分隔符'似乎是一個好的假設,因爲像dirname這樣的函數刪除尾隨分隔符。

然後它總是安全的做:$dir . "/" . $file

即使結果路徑是/home/uploads/../uploads//my_uploads/myfile.ext它仍然會正常工作。

當您需要將路徑存儲在某處時,標準化將變得非常有用。因爲你有這個規範化函數,你可以做出這些假設。


另一個有用的函數是一個函數,用於生成相對路徑。

  • /文件/上傳
  • /files/uploads/my_uploads/myfile.ext

它可以是這兩個路徑獲得有用的,該文件的相對路徑是什麼。


真實路徑

我發現realpath是非常沉重的性能。如果你只是一次調用它,那麼它並不是那麼糟糕,但如果你在一個循環的某個地方做這件事,你會得到相當大的一擊。請記住,每個realpath調用也是對文件系統的調用。另外,如果你傳入一些愚蠢的東西,它會簡單地返回false,我寧願讓它拋出異常。

對我來說,realpath功能是BAD功能的一個很好的例子,因爲它做了兩兩件事:1,規範化的路徑和2.它檢查是否存在的路徑。這兩個功能當然都有用,但它們必須分開。它也不區分文件和目錄。對於Windows來說,這通常不是問題,但對於Linux來說可以。

而且我認爲在Windows上使用realpath("")會有一些奇特的性質。我想它會返回\\ - 這可能是非常不可接受的。


/** 
* This function is a proper replacement for realpath 
* It will _only_ normalize the path and resolve indirections (.. and .) 
* Normalization includes: 
* - directiory separator is always/
* - there is never a trailing directory separator 
* @param $path 
* @return String 
*/ 
function normalize_path($path) { 
    $parts = preg_split(":[\\\/]:", $path); // split on known directory separators 

    // resolve relative paths 
    for ($i = 0; $i < count($parts); $i +=1) { 
     if ($parts[$i] === "..") {   // resolve .. 
      if ($i === 0) { 
       throw new Exception("Cannot resolve path, path seems invalid: `" . $path . "`"); 
      } 
      unset($parts[$i - 1]); 
      unset($parts[$i]); 
      $parts = array_values($parts); 
      $i -= 2; 
     } else if ($parts[$i] === ".") { // resolve . 
      unset($parts[$i]); 
      $parts = array_values($parts); 
      $i -= 1; 
     } 
     if ($i > 0 && $parts[$i] === "") { // remove empty parts 
      unset($parts[$i]); 
      $parts = array_values($parts); 
     } 
    } 
    return implode("/", $parts); 
} 

/** 
* Removes base path from longer path. The resulting path will never contain a leading directory separator 
* Base path must occur in longer path 
* Paths will be normalized 
* @throws Exception 
* @param $base_path 
* @param $longer_path 
* @return string normalized relative path 
*/ 
function make_relative_path($base_path, $longer_path) { 
    $base_path = normalize_path($base_path); 
    $longer_path = normalize_path($longer_path); 
    if (0 !== strpos($longer_path, $base_path)) { 
     throw new Exception("Can not make relative path, base path does not occur at 0 in longer path: `" . $base_path . "`, `" . $longer_path . "`"); 
    } 
    return substr($longer_path, strlen($base_path) + 1); 
} 
+0

+1,但構建一組新零件非常容易。保存整個索引並進行大量計算。 –

4

如果路徑實際存在,您可以使用realpath來擴展它。

echo realpath("/home/../home/dogbert") 
/home/dogbert 
+0

好的,這相當酷,但是有沒有辦法來找出目錄分隔符或有一個標準化的路徑「格式」? – NaN

0

與真實路徑的另一問題是,它不與網址工作的,但串接的邏輯是基本相同的(應該有正好一個斜線之間的兩個相結合的成分)。很明顯,在開頭有兩個斜槓的協議部分是這個規則的例外。但是,將一個URL加入到一起的函數將會非常好。