我碰到這個問題我自己,主要是關於路徑正常化。
規範化是:
- 一個分離器(我選擇了支持,但永遠不會返回向後斜線
\\
)
- 解決間接:
/../
- 刪除重複分隔符:
/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);
}
+1,但構建一組新零件非常容易。保存整個索引並進行大量計算。 –