将外部相对路径转换为绝对路径的PHP方法

4

我正在尝试弄清如何将“外部相对路径”转换为绝对路径: 我真的希望有一个函数可以完成以下操作:

$path = "/search?q=query";
$host = "http://google.com";
$abspath = reltoabs($host, $path);

并且将$abspath设置为"http://google.com/search?q=query"。 另一个例子:

$path = "top.html";
$host = "www.example.com/documentation";
$abspath = reltoabs($host, $path);

请将$abspath设置为"http://www.example.com/documentation/top.html"。

问题在于它不能保证是这种格式,它可能已经是绝对路径,或者指向完全不同的主机,我不太确定如何处理这个问题。谢谢。


如果您可以发布所有不同形式的路径和主机,或者至少有很好的变化,这可能有助于确定如何处理此问题。另外,您从哪里获取这些数据?这可能会有所帮助:http://us3.php.net/manual/en/function.parse-url.php - Kerry Jones
理论上,这个内容将由用户生成,并且可能随处可见: 主机可以是:"google.com","http://www.google.com/prdhp?hl=en&tab=wf"(即它可以包括一个路径),需要从此字符串中提取域。 路径范围可以从:"example.com/donuts" 到 "/testing/n.html",需要检测其中是否有域。 - skeggse
我想我需要澄清一下我的先前评论,即程序提供了两个数据:HOST,它是从中检索URL的站点,以及PATH,它是该站点上可能存在或不存在的路径,如果没有指定域,则需要从HOST中获取域。 - skeggse
3个回答

2

1

所以有三种情况:

  1. 正确的URL
  2. 没有协议
  3. 没有协议和域名

示例代码(未经测试):

if (preg_match('@^http(?:s)?://@i', $userurl))
    $url = preg_replace('@^http(s)?://@i', 'http$1://', $userurl); //protocol lowercase
//deem to have domain if a dot is found before a /
elseif (preg_match('@^[^/]+\\.[^/]+@', $useurl)
    $url = "http://".$useurl;
else { //no protocol or domain
    $url = "http://default.domain/" . (($useurl[0] != "/") ? "/" : "") . $useurl;
}

$url = filter_var($url, FILTER_VALIDATE_URL);

if ($url === false)
    die("User gave invalid url").

路径或主机有哪三种情况? - skeggse

0

看起来我已经解决了自己的问题:

function reltoabs($host, $path) {
    $resulting = array();
    $hostparts = parse_url($host);
    $pathparts = parse_url($path);
    if (array_key_exists("host", $pathparts)) return $path; // Absolute
    // Relative
    $opath = "";
    if (array_key_exists("scheme", $hostparts)) $opath .= $hostparts["scheme"] . "://";
    if (array_key_exists("user", $hostparts)) {
        if (array_key_exists("pass", $hostparts)) $opath .= $hostparts["user"] . ":" . $hostparts["pass"] . "@";
        else $opath .= $hostparts["user"] . "@";
    } elseif (array_key_exists("pass", $hostparts)) $opath .= ":" . $hostparts["pass"] . "@";
    if (array_key_exists("host", $hostparts)) $opath .= $hostparts["host"];
    if (!array_key_exists("path", $pathparts) || $pathparts["path"][0] != "/") {
        $dirname = explode("/", $hostparts["path"]);
        $opath .= implode("/", array_slice($dirname, 0, count($dirname) - 1)) . "/" . basename($pathparts["path"]);
    } else $opath .= $pathparts["path"];
    if (array_key_exists("query", $pathparts)) $opath .= "?" . $pathparts["query"];
    if (array_key_exists("fragment", $pathparts)) $opath .= "#" . $pathparts["fragment"];
    return $opath;
}

对于我的目的来说,这似乎运行得相当不错。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接