将远程相对路径转换为绝对路径

时间:2013-06-15 20:46:30

标签: php html parsing

我尝试寻找类似的问题,但无法做到。

我正在寻找正确方向的推动力。我目前正在做的是 收集远程站点的所有href值的列表,现在因为它们中的一些可以 相对路径,我需要一个构建绝对路径的函数。

因为我有域名(通过使用最后一个网址cUrl):

$base_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);

现在假设$ base_url值是:http://www.example.com/home/index.html 我正在阅读的href值是:/styles/ie.css

我需要将$ base_url的值转换为http://www.example.com/styles/ie.css 但我希望这个功能尽可能地动态化。看看吧 可能的情况(可能不是全部):

1 = base url
2 = relative path
------------------------------------------------
1 http://www.example.com/
2 java/popups.js

1 + 2 = http://www.example.com/java/popups.js
------------------------------------------------
1 http://www.example.com
2 java/popups.js

1 + / + 2 = http://www.example.com/java/popups.js
------------------------------------------------
1 http://www.example.com/mysite/
2 ../java/popups.js 

1 - / + (2 - ..) = http://www.example.com/java/popups.js
------------------------------------------------

1 http://www.example.com/rsc/css/intlhplib-min.css
2 ../images/sunflower.png

1 - /css/intlhplib-min.css + (2 - ..) = http://www.example.com/rsc/images/sunflower.png     

2 个答案:

答案 0 :(得分:1)

我认为你需要在href路径上使用正则表达式来确保它是一致的。您还可以从parse_url()获得准确的基本网址:

<?php
$href = '../images/sunflower.png';
$href = preg_replace('~^\.{0,2}\/~', '', $href);
?>

这里我们从字符串的开头去掉句点和斜杠。然后添加基本网址:

<?php
$url = 'http://www.example.com/home/index.html';
$url = parse_url($url);

$abspath = $url['scheme'] . '://' . $url['host'] . '/' . $href;

echo $abspath;
?>

应输出您想要的内容:http://www.example.com/images/sunflower.png

更新

如果你想要基本网址的第一个目录,那么在解析的网址路径密钥上使用explode:

$first_directory = '';
if (isset($url['path'])) {
    $patharray = explode('/', $url['path']);
    if (count($patharray)>2){
        $first_directory = explode('/', $url['path'])[1] . '/';
    }
}

并将其添加到输出变量:

$abspath = $url['scheme'] . '://' . $url['host'] . '/' . $first_directory . $href;

另一次更新

要查找href值与基本网址的关系,您可以在href值的开头搜索..//的出现,然后相应地调整您的绝对网址。这应该可以帮助您弄清楚场景是什么:

<?php
$href = '../../images/sunflower.png';
preg_match('~^(\.{0,2}\/)+~', $href, $matches); //preg_match to check if it exists
if (substr_count($matches[0], '../')){ // substr_count to count number of '../'
    echo 'Go up ' . substr_count($matches[0], '../') . ' directories';
}
else if (substr_count($matches[0], '/')){
    echo 'Root directory';
}
else {
    echo 'Current directory';
}
?>

检查IDEONE上的演示。

答案 1 :(得分:1)

在从@bozdoz推进正确方向后,我最终编写了自己的函数。

该函数有两个参数,第一个是$ resource,它是相对文件路径。 第二个是基本网址(将用于构建绝对网址)。

这是我的项目设计,我不确定它是否适合任何正在寻找的人 对于类似的解决方案。随意使用它,并提供任何效率改进。

更新版本感谢Tim Cooper

function rel2abs_v2($resource, $base_url) 
{
$base_url = parse_url($base_url);

if(substr($resource, 0, 4) !== "http" && substr($resource, 0, 5) !== "https") // if no http/https is present, then {$resource} is a relative path.
{
# There is a "../" in the string
if (strpos($resource, "../") !== false)
{
$dir_count = substr_count($resource, "../");

$path_array = explode("/", $base_url["path"]);
$path_count = count($path_array); // 4
$path_index = ($path_count - $dir_count) - 2;

$resource = trim(str_replace("../", "", $resource));

if($path_index > 0) { $fs = "/"; }

if($dir_count > 0)
{
$base_url_path = implode("/", array_slice($path_array, $dir_count, $path_index - $dir_count + 1));
return $base_url['scheme'] . '://' . $base_url['host'] . $fs . $base_url_path ."/". $resource;
}
}

# Latest addition - remove if unexplained behaviour is in place.
if(starts_with($resource, "//"))
{
return trim(str_replace("//", "", $resource));      
}

if (starts_with($resource, "/"))
{
return $base_url["scheme"] . "://" . $base_url["host"] . $resource;
}
else
{
$path_array = explode("/", $base_url["path"]);

end($path_array);
$last_id = key($path_array);

return $base_url["scheme"] . "://" . $base_url["host"] . "/" . $path_array[--$last_id] . "/" . $resource;
}

}
else
{
return $resource;
}
} 
相关问题