首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 計算兩檔案相對路徑函式實作與優化

     編輯:PHP 相關知識

在建構模組載入器、資源引用或遷移腳本時,常需計算「檔案 B 相對於檔案 A 的相對路徑」。PHP 內建 realpath() 只能取得絕對路徑,本文提供一個健壯的 getRelativePath() 函式,並說明演算法邏輯與邊界處理。

核心函式

/**
 * 取得 $target 相對於 $base 的相對路徑
 * @param string $base     基準檔案/目錄絕對路徑
 * @param string $target   目標檔案/目錄絕對路徑
 * @return string          相對路徑(如 ../../target/file.php)
 */
function getRelativePath($base, $target) {
    // 統一路徑分隔符並移除尾斜線
    $base = rtrim(str_replace('\\', '/', $base), '/');
    $target = rtrim(str_replace('\\', '/', $target), '/');

    // 分割路徑片段
    $baseParts = explode('/', $base);
    $targetParts = explode('/', $target);

    // 移除檔名(保留目錄層級)
    if (strpos($base, '.') !== false) array_pop($baseParts);
    if (strpos($target, '.') !== false) array_pop($targetParts);

    // 找出共同前綴
    $commonLen = 0;
    while ($commonLen < count($baseParts) && $commonLen < count($targetParts)
           && $baseParts[$commonLen] === $targetParts[$commonLen]) {
        $commonLen++;
    }

    // 計算需向上層級數
    $upLevels = count($baseParts) - $commonLen;

    // 組合相對路徑
    $rel = array_merge(
        array_fill(0, $upLevels, '..'),
        array_slice($targetParts, $commonLen)
    );

    return implode('/', $rel) ?: '.';
}

測試案例

$tests = [
    ['/a/b/c/d/e.php', '/a/b/12/34/c.php', '../../12/34/c.php'],
    ['/var/www/html/index.php', '/var/www/config/app.php', '../config/app.php'],
    ['/home/user/project/src/Controller.php', '/home/user/project/public/index.php', '../../public/index.php'],
    ['/tmp/a/b', '/tmp/a/b', '.'],
    ['/tmp/a/b/', '/tmp/a/b/c', 'c'],
];

foreach ($tests as [$base, $target, $expect]) {
    $result = getRelativePath($base, $target);
    echo "Base: $base\nTarget: $target\nResult: $result " . ($result === $expect ? '✓' : "✗ (expect: $expect)") . "\n\n";
}

演算法解析

  1. 正規化:統一斜線、去尾斜線、去檔名,確保比較的是目錄層級。
  2. 最長共同前綴:逐層比對,找出共享的祖先目錄深度。
  3. 向上回溯:基準路徑超出共同部分的層級數,即為 .. 的數量。
  4. 向下延伸:目標路徑超出共同部分的片段,直接拼接。

進階:支援 Windows 路徑與 URL

// Windows 路徑
getRelativePath('C:\www\a\b', 'C:\www\c\d');   // ..\..\c\d

// URL 路徑(需先 parse_url 取 path)
$urlBase = 'https://example.com/a/b/';
$urlTarget = 'https://example.com/c/d';
getRelativePath(parse_url($urlBase, PHP_URL_PATH), parse_url($urlTarget, PHP_URL_PATH)); // ../c/d

效能優化提示

  • 高頻呼叫時,可將路徑分割結果快取(如用 spl_object_id 做鍵)。
  • PHP 8.1+ 可改用 RelativePath 類(假設未來內建),目前仍需自行實作。

此函式已處理尾斜線、檔名、跨盤符(Windows)、相同路徑等邊界情況,可直接納入專案工具庫。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved