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

PHP 計算兩目錄相對路徑函數實作

     編輯:PHP 相關知識

需求場景

給定兩個絕對路徑,計算從 $a 到 $b 的相對路徑,支援任意深度、跨目錄層級。

核心函數

<?php
/**
 * 計算 $b 相對於 $a 的相對路徑
 * @param string $a 基準路徑 (檔案或目錄)
 * @param string $b 目標路徑 (檔案或目錄)
 * @return string 相對路徑
 */
function getRelativePath(string $a, string $b): string
{
    // 統一處理為目錄路徑
    $a = is_file($a) ? dirname($a) : rtrim($a, '/\\');
    $b = is_file($b) ? dirname($b) : rtrim($b, '/\\');
    
    // 路徑分段
    $aParts = explode('/', $a);
    $bParts = explode('/', $b);
    
    // 找出共同前綴
    $common = 0;
    $minLen = min(count($aParts), count($bParts));
    for ($i = 0; $i < $minLen; $i++) {
        if ($aParts[$i] === $bParts[$i]) {
            $common++;
        } else {
            break;
        }
    }
    
    // 構建相對路徑
    $upLevels = count($aParts) - $common;
    $relative = str_repeat('../', $upLevels);
    $relative .= implode('/', array_slice($bParts, $common));
    
    return $relative ?: '.';
}

// 測試案例
$tests = [
    ['/var/www/project/a.php', '/var/www/project/config/db.php', 'config/db.php'],
    ['/var/www/project/src/Controller', '/var/www/project/public', '../../public'],
    ['/home/user/a/b/c', '/home/user/x/y', '../../../x/y'],
    ['C:/www/a/b', 'C:/www/x/y', '../../x/y'], // Windows 路徑亦適用
];

foreach ($tests as [$a, $b, $expected]) {
    $result = getRelativePath($a, $b);
    echo "A: $a\nB: $b\nExpected: $expected\nGot: $result\n" . ($result === $expected ? '✓' : '✗') . "\n\n";
}
?>

進階版:支援 URL 與 Windows 路徑

<?php
function getRelativePathAdvanced(string $from, string $to): string
{
    // 解析 URL
    if (strpos($from, '://') !== false) {
        $from = parse_url($from, PHP_URL_PATH);
    }
    if (strpos($to, '://') !== false) {
        $to = parse_url($to, PHP_URL_PATH);
    }
    
    // 正規化路徑分隔符
    $from = str_replace('\\', '/', $from);
    $to = str_replace('\\', '/', $to);
    
    // 移除尾部斜線
    $from = rtrim($from, '/');
    $to = rtrim($to, '/');
    
    // 如果是檔案路徑,取目錄
    if (pathinfo($from, PATHINFO_EXTENSION)) $from = dirname($from);
    if (pathinfo($to, PATHINFO_EXTENSION)) $to = dirname($to);
    
    $fromParts = $from ? explode('/', $from) : [];
    $toParts = $to ? explode('/', $to) : [];
    
    // 計算共同前綴長度
    $common = 0;
    foreach ($fromParts as $i => $part) {
        if (!isset($toParts[$i]) || $toParts[$i] !== $part) break;
        $common++;
    }
    
    // 向上層級數
    $up = count($fromParts) - $common;
    // 向下路徑段
    $down = array_slice($toParts, $common);
    
    return str_repeat('../', $up) . implode('/', $down);
}
?>

內建函數替代 (PHP 5.6+)

<?php
// 使用 Symfony Polyfill 或原生 (需啟用)
function getRelativePathNative(string $from, string $to): string
{
    // 將路徑轉為實際檔案系統路徑 (需檔案存在)
    // $from = realpath($from);
    // $to = realpath($to);
    
    // 純字串計算可使用第三方庫:
    // composer require phpstan/phpstan-path-resolver
    // 或 symfony/filesystem
    
    // 簡易版: 利用 SplFileInfo (僅限真實路徑)
    // return (new SplFileInfo($to))->getRelativePath($from); // 不存在此方法
    
    return getRelativePath($from, $to); // 使用上述自訂函數
}
?>

應用場景

  • 模板引擎編譯輸出相對資源路徑
  • CSS/JS 合併時重寫 @import、url() 路徑
  • 靜態站點生成器計算頁面間連結
  • 檔案上傳後生成相對下載連結

純字串運算無需檔案實際存在,效能極高,適合各類路徑轉換需求。

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