You*_*ung 40 php relative-path
当我输入标题时,我注意到有关此问题的一些类似问题,但它们似乎不是在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'
Run Code Online (Sandbox Code Playgroud)
有什么好主意吗?谢谢.
Gor*_*don 64
试试这个:
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);
}
Run Code Online (Sandbox Code Playgroud)
这会给
$a="/home/a.php";
$b="/home/root/b/b.php";
echo getRelativePath($a,$b), PHP_EOL; // ./root/b/b.php
Run Code Online (Sandbox Code Playgroud)
和
$a="/home/apache/a/a.php";
$b="/home/root/b/b.php";
echo getRelativePath($a,$b), PHP_EOL; // ../../root/b/b.php
Run Code Online (Sandbox Code Playgroud)
和
$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
Run Code Online (Sandbox Code Playgroud)
和
$a="/home/apache/htdocs/b/en/b.php";
$b="/home/root/a/a.php";
echo getRelativePath($a,$b), PHP_EOL; // ../../../../root/a/a.php
Run Code Online (Sandbox Code Playgroud)
luc*_*rio 15
由于我们有几个答案,我决定测试它们并对它们进行基准测试.我用这条路来测试:
$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的实现!(标记为答案的那个)
Young的一个也很好用简单的目录结构(比如"a/b/c.php")表现得更好,而Gordon的表现更好,复杂的结构,有很多子目录(比如这个基准测试中使用的子目录).
注意:我在下面写下返回的结果$from和$to作为输入,因此您可以验证其中2个是正常的,而其他2个是错误的:
../../../../../../aaa/bbb/ccc/ddd- >正确../../../../../../aaa/bbb/ccc/ddd- >正确../../../../../../bbb/ccc/ddd- >错了../../../../../aaa/bbb/ccc/ddd- >错了const DS = DIRECTORY_SEPARATOR; // for convenience
function getRelativePath($from, $to) {
$dir = explode(DS, is_file($from) ? dirname($from) : rtrim($from, DS));
$file = explode(DS, $to);
while ($dir && $file && ($dir[0] == $file[0])) {
array_shift($dir);
array_shift($file);
}
return str_repeat('..'.DS, count($dir)) . implode(DS, $file);
}
Run Code Online (Sandbox Code Playgroud)
我的尝试故意简化了,尽管性能可能没有什么不同。我会将基准测试留给好奇的读者练习。但是,这是相当可靠的,并且应该与平台无关。
当心使用array_intersect函数的解决方案,因为如果并行目录具有相同的名称,这些函数将被破坏。例如,getRelativePath('start/A/end/', 'start/B/end/')将返回“ ../end”,因为会array_intersect找到所有相同的名称,在本例中为2时,应该只有1个。
| 归档时间: |
|
| 查看次数: |
29133 次 |
| 最近记录: |