在 PHP 中从绝对路径获取相对路径

2022-08-30 10:43:05

当我键入标题时,我注意到一些关于这个问题的类似问题,但它们似乎不在PHP中。那么使用PHP函数的解决方案是什么呢?

待定。

$a="/home/apache/a/a.php";
$b="/home/root/b/b.php";
$relpath = getRelativePath($a,$b); //needed function,should return '../../root/b/b.php'

有什么好主意吗?谢谢。


答案 1

试试这个:

function getRelativePath($from, $to)
{
    // some compatibility fixes for Windows paths
    $from = is_dir($from) ? rtrim($from, '\/') . '/' : $from;
    $to   = is_dir($to)   ? rtrim($to, '\/') . '/'   : $to;
    $from = str_replace('\\', '/', $from);
    $to   = str_replace('\\', '/', $to);

    $from     = explode('/', $from);
    $to       = explode('/', $to);
    $relPath  = $to;

    foreach($from as $depth => $dir) {
        // find first non-matching dir
        if($dir === $to[$depth]) {
            // ignore this directory
            array_shift($relPath);
        } else {
            // get number of remaining dirs to $from
            $remaining = count($from) - $depth;
            if($remaining > 1) {
                // add traversals up to first matching dir
                $padLength = (count($relPath) + $remaining - 1) * -1;
                $relPath = array_pad($relPath, $padLength, '..');
                break;
            } else {
                $relPath[0] = './' . $relPath[0];
            }
        }
    }
    return implode('/', $relPath);
}

这将给予

$a="/home/a.php";
$b="/home/root/b/b.php";
echo getRelativePath($a,$b), PHP_EOL;  // ./root/b/b.php

$a="/home/apache/a/a.php";
$b="/home/root/b/b.php";
echo getRelativePath($a,$b), PHP_EOL; // ../../root/b/b.php

$a="/home/root/a/a.php";
$b="/home/apache/htdocs/b/en/b.php";
echo getRelativePath($a,$b), PHP_EOL; // ../../apache/htdocs/b/en/b.php

$a="/home/apache/htdocs/b/en/b.php";
$b="/home/root/a/a.php";
echo getRelativePath($a,$b), PHP_EOL; // ../../../../root/a/a.php

答案 2

由于我们有几个答案,我决定测试它们并对其进行基准测试。我用这个路径来测试:

$from = "/var/www/sites/web/mainroot/webapp/folder/sub/subf/subfo/subfol/subfold/lastfolder/";注意:如果它是一个文件夹,则必须放置一个尾部斜杠才能使函数正常工作!所以,将不起作用。改用或__DIR____FILE____DIR__ . '/'

$to = "/var/www/sites/web/mainroot/webapp/folder/aaa/bbb/ccc/ddd";

结果:(小数分隔符为逗号,千位分隔符为点)

  • Gordon 的函数:结果正确,时间为 100.000 execs 1,222
  • 杨的函数:结果正确,时间为100.000 execs 1,540
  • Ceagle的函数:结果错误(它适用于某些路径,但与其他一些路径一起失败,例如测试中使用的路径和上面写的路径)
  • Loranger的函数:结果错误(它适用于某些路径,但与其他一些路径一起失败,例如测试中使用的路径和上面编写的路径)

所以,我建议你使用戈登的实现!(标记为答案的那个)

Young的那个也很好,在简单的目录结构(如“a / b / c.php)下表现更好,而Gordon的那个在复杂结构,具有许多子目录(如本基准中使用的子目录)时表现更好。


注意:我在这里写下返回的结果和作为输入返回的结果,因此您可以验证其中2个是可以的,而其他2个是错误的:$from$to

  • 戈登:-->正确../../../../../../aaa/bbb/ccc/ddd
  • 年轻: --> 正确../../../../../../aaa/bbb/ccc/ddd
  • 塞格尔:-->错了../../../../../../bbb/ccc/ddd
  • 洛兰格: -->错了../../../../../aaa/bbb/ccc/ddd

推荐