相对URL转绝对URL

话不多说,先贡献代码。

<?php

// 相对URL转绝对URL
function url2absolute($href, $currentUrl = '')
{
    // 去除前后空格,如果是 空字符串,锚点,或者议协议开头 则没必要继续解析下去了
    $href = trim($href);
    if ($href === '' || strpos($href, '#') === 0) {
        return $currentUrl ? $currentUrl : $href;
    }
    if (preg_match('/^[a-z]+:/i', $href)) {
        return $href;
    }


    // 结果路径
    $url = '';

    // 转换所有 '\'
    $url = preg_replace('/\\\\/', '/', $href);

    // 去除所有 './'
    $url = preg_replace('/(?<!\.)\.\//', '', $url);

    // 迭代去除所有的 '/abc/../'
    $patternUpper = '/(?<!\/)\/([^\/]{1,}?)\/\.\.\//';
    $count = preg_match_all($patternUpper, $url, $matches);
    do {
        $url = preg_replace($patternUpper, '/', $url);
        $count = preg_match_all($patternUpper, $url, $matches);
    } while ($count >= 1);

    // 除去最后的 '/..'
    $url = preg_replace('/(?<!\/)\/([^\/]{1,}?)\/\.\.$/', '/', $url);
    $url = preg_replace('/\/\.\.$/', '', $url);

    // 除去存在的 '../'
    $url = preg_replace('/(?<!\.)\.\.\//', '', $url);


    // 替换域名
    if (stripos($url, 'http') !== 0 && $currentUrl) {
        // 解析当前URL
        if (filter_var($currentUrl, FILTER_VALIDATE_URL)) {
            if (strpos($url, '/') === 0) {
                $currentUrlPart = parse_url($currentUrl);
                $currentUrlDomain = $currentUrlPart['scheme'] . '://' . $currentUrlPart['host'] . (isset($currentUrlPart['port']) ? (':' . $currentUrlPart['port']) : '');
                $url = rtrim($currentUrlDomain, '/') . '/' . ltrim($url, '/');
            } else {
                $url = rtrim($currentUrl, '/') . '/' . $url;
            }
        }
    }

    return $url;
}

$href = '/a/b/../a/../c/../a/./a/../a/';
$currentUrl = 'https://138.139.90.1:8888/summary/';
var_dump(url2absolute($href, $currentUrl));

PS:
之前在做爬虫的时候,遇到那种href不全的网站,需要去手动拼接。后面我自己写了一个函数fix,效果还是不行(自己写得烂,当时没啥思路)。今天闲暇时,有想起这个问题,然后网上找找看,找到了这篇文章 https://www.jb51.net/article/106971.htm ,思路中规中矩的,膜拜大佬。本文函数中间部分借鉴了前辈的代码。
头和尾是我加上去优化的,方便使用。

添加新评论