首先原題是這樣子的:
php
寫一個函數,計算出兩個文件的相對路徑,如 $a = '/a/b/c/d/d.php',$b = '/a/b/1/2/c.php'函數
計算出的$b相對於$a的相對路徑應該是:../../c/d測試
那麼對於網上給出的答案,看了看貌似只能針對題目中給出的那個路徑來計算,若是路徑一變化,相似下面這樣,那麼那些程序好像沒用了,固然有些是有用,可是仍是報一些警告出來。。。。。spa
例如:code
$a = '/a/b/c/d/e/f/g/h/e.php'get
$b = '/a/b/1/2/c.php'string
再例如:io
$a = '/a/e.php'function
$b = '/a/b/c/d/1/2/c.php'class
再例如:
$a = '/a/b/c/d/d.php'
$b = '/a/b/c/d/c.php'
因此這個狀況挺多的,不能僅僅看當下的需求!
首先仍是說下這個題目的意圖吧,它的要求是求$b相對於$a的一個相對路徑,也就是說是個什麼意思呢。
就是從$b所給定的那個文件經過相對路徑的方式表示怎麼樣能夠找到$a所對應的那個文件。就那題目給出的那個路徑來解釋,就是咱們怎麼$b到達$a呢,那首先從$b出發須要「../」上一級目錄而後再「../」上一級目錄來到了「/a/b」這個目錄下,而後接着再從這個目錄下出發,鏈接上「/c/d」而後就來到了$a所對應的目錄。
也就是說,這個題目的主要任務是找到從$b到$a須要「上幾級」才能到達和$a具備相同目錄的地方,而後接着鏈接上$a接下來的那部分,那麼咱們就獲得了答案,因此題目的關鍵是找到底須要「上幾級」!
廢話很少說,直接看代碼:
/** * 計算$b相對於$a的相對路徑 * @param string $a * @param string $b * @return string */ function getRelativePath($a, $b) { $relativePath = ""; $pathA = explode('/', dirname($a)); $pathB = explode('/', dirname($b)); $n = 0; $len = count($pathB) > count($pathA) ? count($pathA) : count($pathB); do { if ( $n >= $len || $pathA[$n] != $pathB[$n] ) { break; } } while (++$n); $relativePath .= str_repeat('../', count($pathB) - $n); $relativePath .= implode('/', array_splice($pathA, $n)); return $relativePath; } $res = getRelativePath($a, $b); var_dump($res);
通過測試呢,上面列舉的狀況都知足。
那這段程序須要解釋的就是:
$len爲何須要求出$a和$b中路徑最少的一個?
那是由於下面咱們經過do{}while();循環來從0即起始路徑開始向下一直對比$a和$b的路徑,但願找到是從哪一個路徑開始致使$a和$b不同了,也就是從找到了$a和$b路徑總共相同的路徑數是幾個了。那在尋找的過程當中,若是出現$a和$b的路徑一直不相等那麼$n會一直增長致使陷入死循環,因此還須要另一個條件,就是咱們須要讓$n的最大值不能超過$a和$b中路徑最短的一個,爲何呢?由於$n一旦大於了$len那說明有一個路徑已經結束了,那直到結束也沒有找到$a和$b不同的那個部分,那說明其中最短路徑的長度正好是他們路徑相同的數目。(多數其它程序就範了這個錯誤),也就不須要繼續找了,由於咱們已經找到了。
找到了相同路徑的個數以後,首先須要計算的是:從$b到$a到底須要幾個「../」,那麼計算方法就是用「count($pathB) - $n」,爲何呢?由於$n表示路徑相同的數目,而「 count($pathB)」表示$b的路徑數,那麼相互一減就獲得了不一樣的路徑數目也就是須要的幾個「../」,那麼減完以後的結果必定是大於等0的值,因此沒問題!
找到了從$b到$a須要幾個「../」以後的任務就是將這幾個「../」和$a中不一樣的路徑部分拼接一下就能夠了,也就是代碼:$relativePath .= implode('/', array_splice($pathA, $n));
到此,結束!