使用PHP将相对路径转换为绝对URL

发布于 2024-10-07 07:36:26 字数 28 浏览 0 评论 0原文

如何使用php将相对路径转换为绝对URL?

How to, using php, transform relative path to absolute URL?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

梦幻之岛 2024-10-14 07:36:26
function rel2abs($rel, $base)
{
    /* return if already absolute URL */
    if (parse_url($rel, PHP_URL_SCHEME) != '') return $rel;

    /* queries and anchors */
    if ($rel[0]=='#' || $rel[0]=='?') return $base.$rel;

    /* parse base URL and convert to local variables:
       $scheme, $host, $path */
    extract(parse_url($base));

    /* remove non-directory element from path */
    $path = preg_replace('#/[^/]*$#', '', $path);

    /* destroy path if relative url points to root */
    if ($rel[0] == '/') $path = '';

    /* dirty absolute URL */
    $abs = "$host$path/$rel";

    /* replace '//' or '/./' or '/foo/../' with '/' */
    $re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#');
    for($n=1; $n>0; $abs=preg_replace($re, '/', $abs, -1, $n)) {}

    /* absolute URL is ready! */
    return $scheme.'://'.$abs;
}
function rel2abs($rel, $base)
{
    /* return if already absolute URL */
    if (parse_url($rel, PHP_URL_SCHEME) != '') return $rel;

    /* queries and anchors */
    if ($rel[0]=='#' || $rel[0]=='?') return $base.$rel;

    /* parse base URL and convert to local variables:
       $scheme, $host, $path */
    extract(parse_url($base));

    /* remove non-directory element from path */
    $path = preg_replace('#/[^/]*$#', '', $path);

    /* destroy path if relative url points to root */
    if ($rel[0] == '/') $path = '';

    /* dirty absolute URL */
    $abs = "$host$path/$rel";

    /* replace '//' or '/./' or '/foo/../' with '/' */
    $re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#');
    for($n=1; $n>0; $abs=preg_replace($re, '/', $abs, -1, $n)) {}

    /* absolute URL is ready! */
    return $scheme.'://'.$abs;
}
征﹌骨岁月お 2024-10-14 07:36:26

我喜欢 jordanstephens 从链接中提供的代码!我投了赞成票。 l0oky 启发我确保该函数与端口、用户名和密码 URL 兼容。我的项目需要它。

function rel2abs( $rel, $base )
{
    /* return if already absolute URL */
    if( parse_url($rel, PHP_URL_SCHEME) != '' )
        return( $rel );

    /* queries and anchors */
    if( $rel[0]=='#' || $rel[0]=='?' )
        return( $base.$rel );

    /* parse base URL and convert to local variables:
       $scheme, $host, $path */
    extract( parse_url($base) );

    /* remove non-directory element from path */
    $path = preg_replace( '#/[^/]*$#', '', $path );

    /* destroy path if relative url points to root */
    if( $rel[0] == '/' )
        $path = '';

    /* dirty absolute URL */
    $abs = '';

    /* do we have a user in our URL? */
    if( isset($user) )
    {
        $abs.= $user;

        /* password too? */
        if( isset($pass) )
            $abs.= ':'.$pass;

        $abs.= '@';
    }

    $abs.= $host;

    /* did somebody sneak in a port? */
    if( isset($port) )
        $abs.= ':'.$port;

    $abs.=$path.'/'.$rel;

    /* replace '//' or '/./' or '/foo/../' with '/' */
    $re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#');
    for( $n=1; $n>0; $abs=preg_replace( $re, '/', $abs, -1, $n ) ) {}

    /* absolute URL is ready! */
    return( $scheme.'://'.$abs );
}

I love the code that jordanstephens provided from the link! I voted it up. l0oky inspired me to make sure that the function is port, username, and password URL compatible. I needed it for my project.

function rel2abs( $rel, $base )
{
    /* return if already absolute URL */
    if( parse_url($rel, PHP_URL_SCHEME) != '' )
        return( $rel );

    /* queries and anchors */
    if( $rel[0]=='#' || $rel[0]=='?' )
        return( $base.$rel );

    /* parse base URL and convert to local variables:
       $scheme, $host, $path */
    extract( parse_url($base) );

    /* remove non-directory element from path */
    $path = preg_replace( '#/[^/]*$#', '', $path );

    /* destroy path if relative url points to root */
    if( $rel[0] == '/' )
        $path = '';

    /* dirty absolute URL */
    $abs = '';

    /* do we have a user in our URL? */
    if( isset($user) )
    {
        $abs.= $user;

        /* password too? */
        if( isset($pass) )
            $abs.= ':'.$pass;

        $abs.= '@';
    }

    $abs.= $host;

    /* did somebody sneak in a port? */
    if( isset($port) )
        $abs.= ':'.$port;

    $abs.=$path.'/'.$rel;

    /* replace '//' or '/./' or '/foo/../' with '/' */
    $re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#');
    for( $n=1; $n>0; $abs=preg_replace( $re, '/', $abs, -1, $n ) ) {}

    /* absolute URL is ready! */
    return( $scheme.'://'.$abs );
}
超可爱的懒熊 2024-10-14 07:36:26

添加了对保留当前查询的支持。对 ?page=1 等有很大帮助...

function rel2abs($rel, $base)
{
    /* return if already absolute URL */
    if (parse_url($rel, PHP_URL_SCHEME) != '')
        return ($rel);

    /* queries and anchors */
    if ($rel[0] == '#' || $rel[0] == '?')
        return ($base . $rel);

    /* parse base URL and convert to local variables: $scheme, $host, $path, $query, $port, $user, $pass */
    extract(parse_url($base));

    /* remove non-directory element from path */
    $path = preg_replace('#/[^/]*$#', '', $path);

    /* destroy path if relative url points to root */
    if ($rel[0] == '/')
        $path = '';

    /* dirty absolute URL */
    $abs = '';

    /* do we have a user in our URL? */
    if (isset($user)) {
        $abs .= $user;

        /* password too? */
        if (isset($pass))
            $abs .= ':' . $pass;

        $abs .= '@';
    }

    $abs .= $host;

    /* did somebody sneak in a port? */
    if (isset($port))
        $abs .= ':' . $port;

    $abs .= $path . '/' . $rel . (isset($query) ? '?' . $query : '');

    /* replace '//' or '/./' or '/foo/../' with '/' */
    $re = ['#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#'];
    for ($n = 1; $n > 0; $abs = preg_replace($re, '/', $abs, -1, $n)) {
    }

    /* absolute URL is ready! */

    return ($scheme . '://' . $abs);
}

Added support to keep the current query. Helps a lot for ?page=1 and so on...

function rel2abs($rel, $base)
{
    /* return if already absolute URL */
    if (parse_url($rel, PHP_URL_SCHEME) != '')
        return ($rel);

    /* queries and anchors */
    if ($rel[0] == '#' || $rel[0] == '?')
        return ($base . $rel);

    /* parse base URL and convert to local variables: $scheme, $host, $path, $query, $port, $user, $pass */
    extract(parse_url($base));

    /* remove non-directory element from path */
    $path = preg_replace('#/[^/]*$#', '', $path);

    /* destroy path if relative url points to root */
    if ($rel[0] == '/')
        $path = '';

    /* dirty absolute URL */
    $abs = '';

    /* do we have a user in our URL? */
    if (isset($user)) {
        $abs .= $user;

        /* password too? */
        if (isset($pass))
            $abs .= ':' . $pass;

        $abs .= '@';
    }

    $abs .= $host;

    /* did somebody sneak in a port? */
    if (isset($port))
        $abs .= ':' . $port;

    $abs .= $path . '/' . $rel . (isset($query) ? '?' . $query : '');

    /* replace '//' or '/./' or '/foo/../' with '/' */
    $re = ['#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#'];
    for ($n = 1; $n > 0; $abs = preg_replace($re, '/', $abs, -1, $n)) {
    }

    /* absolute URL is ready! */

    return ($scheme . '://' . $abs);
}
波浪屿的海角声 2024-10-14 07:36:26

Web 浏览器使用页面 URL 或 基本标记 来解析相对 URL。

该 PHP 脚本旨在解析相对于基本 URL 的 URL。

/** 
 * Builds a complete URL from its individual components.
 *
 * @param array $parts An associative array representing the components of a URL (following the parse_url scheme).
 * @return string The constructed URL.
 */
function build_url($parts)
{
    if (empty($parts['user'])) {
        $url = $parts['scheme'] . '://' . $parts['host'];
    } elseif(empty($parts['pass'])) {
        $url = $parts['scheme'] . '://' . $parts['user'] . '@' . $parts['host'];
    } else {
        $url = $parts['scheme'] . '://' . $parts['user'] . ':' . $parts['pass'] . '@' . $parts['host'];
    }

    if (!empty($parts['port'])) {
        $url .= ':' . $parts['port'];
    }

    if (!empty($parts['path'])) {
        $url .= $parts['path'];
    }

    if (!empty($parts['query'])) {
        $url .= '?' . $parts['query'];
    }

    if (!empty($parts['fragment'])) {
        return $url . '#' . $parts['fragment'];
    }

    return $url;
}

/** 
 * Converts a relative path into an absolute path.
 *
 * @param string $path The relative path.
 * @return string The absolute path.
 */
function abs_path($path)
{
    $path_array = explode('/', $path);

    // Solve current and parent folder navigation
    $translated_path_array = array();
    $i = 0;
    foreach ($path_array as $name) {
        if ($name === '..') {
            unset($translated_path_array[--$i]);
        } elseif (!empty($name) && $name !== '.') {
            $translated_path_array[$i++] = $name;
        }
    }

    return '/' . implode('/', $translated_path_array);
}

/** 
 * Converts a relative URL into an absolute URL using a base URL for reference.
 *
 * @param string $url The relative URL.
 * @param string $base The absolute URL serving as the reference point.
 * @return string The absolute URL.
 */
function abs_url($url, $base)
{
    $url_parts = parse_url($url);
    $base_parts = parse_url($base);

    // Handle the path if it is specified
    if (!empty($url_parts['path'])) {
        // Check if the path should be appended to the base path
        if (substr($url_parts['path'], 0, 1) !== '/') {
            if (substr($base_parts['path'], -1) === '/') {
                $url_parts['path'] = $base_parts['path'] . $url_parts['path'];
            } else {
                $url_parts['path'] = dirname($base_parts['path']) . '/' . $url_parts['path'];
            }
        }

        // Make the path absolute
        $url_parts['path'] = abs_path($url_parts['path']);
    }

    // Use the base URL to populate the unfilled components up to the first filled component
    foreach (['scheme', 'host', 'path', 'query', 'fragment'] as $comp) {
        if (!empty($url_parts[$comp])) {
            break;
        }
        $url_parts[$comp] = $base_parts[$comp];
    }

    // Build and return the absolute URL
    return build_url($url_parts);
}

测试

// A base URL.
$base_url = 'https://example.com/path1/path2/path3/path4/file.ext?field1=value1&field2=value2#fragment';

// Relative URLs (underscore is used to indicate what is derived from a relative URL).
$test_urls = array(
    "http://_example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment", // URL
    "//_example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment",      // URL without scheme
    "//_example.com",                                                                        // URL with host only
    "/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment",                    // URL without scheme and host
    "_path1/_path2/_file.ext",                                                               // Only path
    "./../../_path1/../_path2/file.ext#_fragment",                                           // URL with path and fragment
    "?_field1=_value1&_field2=_value2#_fragment",                                            // URL with query and fragment
    "#_fragment"                                                                             // Only fragment
);

// The expected results.
$expected_urls = array(
    "http://_example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment",
    "https://_example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment",
    "https://_example.com",
    "https://example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment",
    "https://example.com/path1/path2/path3/path4/_path1/_path2/_file.ext",
    "https://example.com/path1/path2/_path2/file.ext#_fragment",
    "https://example.com/path1/path2/path3/path4/file.ext?_field1=_value1&_field2=_value2#_fragment",
    "https://example.com/path1/path2/path3/path4/file.ext?field1=value1&field2=value2#_fragment"
);

foreach ($test_urls as $i => $url) {
    $abs_url = abs_url($url, $base_url);
    if ( $abs_url == $expected_urls[$i] ) {
        echo  "[OK] " . $abs_url . PHP_EOL;
    } else {
        echo  "[WRONG] " . $abs_url . PHP_EOL;
    }
}

结果

[OK] http://_example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment
[OK] https://_example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment
[OK] https://_example.com
[OK] https://example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment
[OK] https://example.com/path1/path2/path3/path4/_path1/_path2/_file.ext
[OK] https://example.com/path1/path2/_path2/file.ext#_fragment
[OK] https://example.com/path1/path2/path3/path4/file.ext?_field1=_value1&_field2=_value2#_fragment
[OK] https://example.com/path1/path2/path3/path4/file.ext?field1=value1&field2=value2#_fragment

A web browser uses the page URL or the base tag to resolve relative URLs.

This PHP script is designed to resolve a URL relative to a base URL.

/** 
 * Builds a complete URL from its individual components.
 *
 * @param array $parts An associative array representing the components of a URL (following the parse_url scheme).
 * @return string The constructed URL.
 */
function build_url($parts)
{
    if (empty($parts['user'])) {
        $url = $parts['scheme'] . '://' . $parts['host'];
    } elseif(empty($parts['pass'])) {
        $url = $parts['scheme'] . '://' . $parts['user'] . '@' . $parts['host'];
    } else {
        $url = $parts['scheme'] . '://' . $parts['user'] . ':' . $parts['pass'] . '@' . $parts['host'];
    }

    if (!empty($parts['port'])) {
        $url .= ':' . $parts['port'];
    }

    if (!empty($parts['path'])) {
        $url .= $parts['path'];
    }

    if (!empty($parts['query'])) {
        $url .= '?' . $parts['query'];
    }

    if (!empty($parts['fragment'])) {
        return $url . '#' . $parts['fragment'];
    }

    return $url;
}

/** 
 * Converts a relative path into an absolute path.
 *
 * @param string $path The relative path.
 * @return string The absolute path.
 */
function abs_path($path)
{
    $path_array = explode('/', $path);

    // Solve current and parent folder navigation
    $translated_path_array = array();
    $i = 0;
    foreach ($path_array as $name) {
        if ($name === '..') {
            unset($translated_path_array[--$i]);
        } elseif (!empty($name) && $name !== '.') {
            $translated_path_array[$i++] = $name;
        }
    }

    return '/' . implode('/', $translated_path_array);
}

/** 
 * Converts a relative URL into an absolute URL using a base URL for reference.
 *
 * @param string $url The relative URL.
 * @param string $base The absolute URL serving as the reference point.
 * @return string The absolute URL.
 */
function abs_url($url, $base)
{
    $url_parts = parse_url($url);
    $base_parts = parse_url($base);

    // Handle the path if it is specified
    if (!empty($url_parts['path'])) {
        // Check if the path should be appended to the base path
        if (substr($url_parts['path'], 0, 1) !== '/') {
            if (substr($base_parts['path'], -1) === '/') {
                $url_parts['path'] = $base_parts['path'] . $url_parts['path'];
            } else {
                $url_parts['path'] = dirname($base_parts['path']) . '/' . $url_parts['path'];
            }
        }

        // Make the path absolute
        $url_parts['path'] = abs_path($url_parts['path']);
    }

    // Use the base URL to populate the unfilled components up to the first filled component
    foreach (['scheme', 'host', 'path', 'query', 'fragment'] as $comp) {
        if (!empty($url_parts[$comp])) {
            break;
        }
        $url_parts[$comp] = $base_parts[$comp];
    }

    // Build and return the absolute URL
    return build_url($url_parts);
}

Test

// A base URL.
$base_url = 'https://example.com/path1/path2/path3/path4/file.ext?field1=value1&field2=value2#fragment';

// Relative URLs (underscore is used to indicate what is derived from a relative URL).
$test_urls = array(
    "http://_example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment", // URL
    "//_example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment",      // URL without scheme
    "//_example.com",                                                                        // URL with host only
    "/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment",                    // URL without scheme and host
    "_path1/_path2/_file.ext",                                                               // Only path
    "./../../_path1/../_path2/file.ext#_fragment",                                           // URL with path and fragment
    "?_field1=_value1&_field2=_value2#_fragment",                                            // URL with query and fragment
    "#_fragment"                                                                             // Only fragment
);

// The expected results.
$expected_urls = array(
    "http://_example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment",
    "https://_example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment",
    "https://_example.com",
    "https://example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment",
    "https://example.com/path1/path2/path3/path4/_path1/_path2/_file.ext",
    "https://example.com/path1/path2/_path2/file.ext#_fragment",
    "https://example.com/path1/path2/path3/path4/file.ext?_field1=_value1&_field2=_value2#_fragment",
    "https://example.com/path1/path2/path3/path4/file.ext?field1=value1&field2=value2#_fragment"
);

foreach ($test_urls as $i => $url) {
    $abs_url = abs_url($url, $base_url);
    if ( $abs_url == $expected_urls[$i] ) {
        echo  "[OK] " . $abs_url . PHP_EOL;
    } else {
        echo  "[WRONG] " . $abs_url . PHP_EOL;
    }
}

Result

[OK] http://_example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment
[OK] https://_example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment
[OK] https://_example.com
[OK] https://example.com/_path1/_path2/_file.ext?_field1=_value1&_field2=_value2#_fragment
[OK] https://example.com/path1/path2/path3/path4/_path1/_path2/_file.ext
[OK] https://example.com/path1/path2/_path2/file.ext#_fragment
[OK] https://example.com/path1/path2/path3/path4/file.ext?_field1=_value1&_field2=_value2#_fragment
[OK] https://example.com/path1/path2/path3/path4/file.ext?field1=value1&field2=value2#_fragment
心在旅行 2024-10-14 07:36:26

我更新了该函数以修复以“//”开头的相对 URL,从而提高了执行速度。

function getAbsoluteUrl($relativeUrl, $baseUrl){

    // if already absolute URL 
    if (parse_url($relativeUrl, PHP_URL_SCHEME) !== null){
        return $relativeUrl;
    }

    // queries and anchors
    if ($relativeUrl[0] === '#' || $relativeUrl[0] === '?'){
        return $baseUrl.$relativeUrl;
    }

    // parse base URL and convert to: $scheme, $host, $path, $query, $port, $user, $pass
    extract(parse_url($baseUrl));

    // if base URL contains a path remove non-directory elements from $path
    if (isset($path) === true){
        $path = preg_replace('#/[^/]*$#', '', $path);
    }
    else {
        $path = '';
    }

    // if realtive URL starts with //
    if (substr($relativeUrl, 0, 2) === '//'){
        return $scheme.':'.$relativeUrl;
    }

    // if realtive URL starts with /
    if ($relativeUrl[0] === '/'){
        $path = null;
    }

    $abs = null;

    // if realtive URL contains a user
    if (isset($user) === true){
        $abs .= $user;

        // if realtive URL contains a password
        if (isset($pass) === true){
            $abs .= ':'.$pass;
        }

        $abs .= '@';
    }

    $abs .= $host;

    // if realtive URL contains a port
    if (isset($port) === true){
        $abs .= ':'.$port;
    }

    $abs .= $path.'/'.$relativeUrl.(isset($query) === true ? '?'.$query : null);

    // replace // or /./ or /foo/../ with /
    $re = ['#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#'];
    for ($n = 1; $n > 0; $abs = preg_replace($re, '/', $abs, -1, $n)) {
    }

    // return absolute URL
    return $scheme.'://'.$abs;

}

I updated the function to fix relative URL starting with '//' improving execution speed.

function getAbsoluteUrl($relativeUrl, $baseUrl){

    // if already absolute URL 
    if (parse_url($relativeUrl, PHP_URL_SCHEME) !== null){
        return $relativeUrl;
    }

    // queries and anchors
    if ($relativeUrl[0] === '#' || $relativeUrl[0] === '?'){
        return $baseUrl.$relativeUrl;
    }

    // parse base URL and convert to: $scheme, $host, $path, $query, $port, $user, $pass
    extract(parse_url($baseUrl));

    // if base URL contains a path remove non-directory elements from $path
    if (isset($path) === true){
        $path = preg_replace('#/[^/]*$#', '', $path);
    }
    else {
        $path = '';
    }

    // if realtive URL starts with //
    if (substr($relativeUrl, 0, 2) === '//'){
        return $scheme.':'.$relativeUrl;
    }

    // if realtive URL starts with /
    if ($relativeUrl[0] === '/'){
        $path = null;
    }

    $abs = null;

    // if realtive URL contains a user
    if (isset($user) === true){
        $abs .= $user;

        // if realtive URL contains a password
        if (isset($pass) === true){
            $abs .= ':'.$pass;
        }

        $abs .= '@';
    }

    $abs .= $host;

    // if realtive URL contains a port
    if (isset($port) === true){
        $abs .= ':'.$port;
    }

    $abs .= $path.'/'.$relativeUrl.(isset($query) === true ? '?'.$query : null);

    // replace // or /./ or /foo/../ with /
    $re = ['#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#'];
    for ($n = 1; $n > 0; $abs = preg_replace($re, '/', $abs, -1, $n)) {
    }

    // return absolute URL
    return $scheme.'://'.$abs;

}
撩动你心 2024-10-14 07:36:26

实际上不是关于转换路径而不是网址的问题吗? PHP 实际上有一个用于此目的的函数:realpath()。您唯一应该注意的是符号链接。

PHP 手册中的示例:

chdir('/var/www/');
echo realpath('./../../etc/passwd') . PHP_EOL;
// Prints: /etc/passwd

echo realpath('/tmp/') . PHP_EOL;
// Prints: /tmp

Wasn't in fact the question about converting path and not url? PHP actually has a function for this: realpath(). The only thing you should be aware of are symlinks.

Example from PHP manual:

chdir('/var/www/');
echo realpath('./../../etc/passwd') . PHP_EOL;
// Prints: /etc/passwd

echo realpath('/tmp/') . PHP_EOL;
// Prints: /tmp
﹏半生如梦愿梦如真 2024-10-14 07:36:26

一个简单的方法是使用 phpUri 一个小型 php 库用于将相对 URL 转换为绝对 URL。

用法很简单:

require_once 'phpuri.php';
$absolute = phpUri::parse( $base_path )->join( $relative_path );

您甚至不需要检查传递给 join 的路径实际上是相对的。如果它是绝对的,那么parse将返回它。

A easy way to do this is using phpUri a small php library for converting relative urls to absolute.

Usage is simple:

require_once 'phpuri.php';
$absolute = phpUri::parse( $base_path )->join( $relative_path );

You don't even need to check that the path passed to join is actually relative. If it is absolute then parse will return it.

蓝天 2024-10-14 07:36:26

如果您的项目中已经有 Guzzle,您可以利用它的 URL 实现:

use GuzzleHttp\Psr7\UriResolver;
use GuzzleHttp\Psr7\Utils as Psr7Utils;

$baseUri = Psr7Utils::uriFor($baseUrl);
$absoluteUrl = (string) UriResolver::resolve(
    $baseUri, Psr7Utils::uriFor($relativeUrl)
);

If you already have Guzzle in your project you can utilize its URL implementation:

use GuzzleHttp\Psr7\UriResolver;
use GuzzleHttp\Psr7\Utils as Psr7Utils;

$baseUri = Psr7Utils::uriFor($baseUrl);
$absoluteUrl = (string) UriResolver::resolve(
    $baseUri, Psr7Utils::uriFor($relativeUrl)
);
暮倦 2024-10-14 07:36:26

如果相对目录已经存在,这将完成这项工作:

function rel2abs($relPath, $baseDir = './')
{ 
if ('' == trim($path))
{
    return $baseDir;
    }
    $currentDir = getcwd();
    chdir($baseDir);
    $path = realpath($path);
    chdir($currentDir);
    return $path;
}

If the relative directory already exists this will do the job:

function rel2abs($relPath, $baseDir = './')
{ 
if ('' == trim($path))
{
    return $baseDir;
    }
    $currentDir = getcwd();
    chdir($baseDir);
    $path = realpath($path);
    chdir($currentDir);
    return $path;
}
灯下孤影 2024-10-14 07:36:26

我使用了相同的代码: http://nashruddin.com/PHP_Script_for_Converting_Relative_to_Absolute_URL
但我对其进行了一些修改,因此如果基本 url 包含端口号,它将返回其中包含端口号的相对 URL。

function rel2abs($rel, $base)
{
    /* return if already absolute URL */
    if (parse_url($rel, PHP_URL_SCHEME) != '') return $rel;

    /* queries and anchors */
    if ($rel[0]=='#' || $rel[0]=='?') return $base.$rel;

    /* parse base URL and convert to local variables:
       $scheme, $host, $path */
    extract(parse_url($base));

    /* remove non-directory element from path */
    $path = preg_replace('#/[^/]*$#', '', $path);

    /* destroy path if relative url points to root */
    if ($rel[0] == '/') $path = '';

    /* dirty absolute URL // with port number if exists */
    if (parse_url($base, PHP_URL_PORT) != ''){
        $abs = "$host:".parse_url($base, PHP_URL_PORT)."$path/$rel";
    }else{
        $abs = "$host$path/$rel";
    }
    /* replace '//' or '/./' or '/foo/../' with '/' */
    $re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#');
    for($n=1; $n>0; $abs=preg_replace($re, '/', $abs, -1, $n)) {}

    /* absolute URL is ready! */
    return $scheme.'://'.$abs;
}

希望这对某人有帮助!

I used the same code from: http://nashruddin.com/PHP_Script_for_Converting_Relative_to_Absolute_URL
but I modified It a little bit so If base url contains PORT number it returns the relative URL with port number in it.

function rel2abs($rel, $base)
{
    /* return if already absolute URL */
    if (parse_url($rel, PHP_URL_SCHEME) != '') return $rel;

    /* queries and anchors */
    if ($rel[0]=='#' || $rel[0]=='?') return $base.$rel;

    /* parse base URL and convert to local variables:
       $scheme, $host, $path */
    extract(parse_url($base));

    /* remove non-directory element from path */
    $path = preg_replace('#/[^/]*$#', '', $path);

    /* destroy path if relative url points to root */
    if ($rel[0] == '/') $path = '';

    /* dirty absolute URL // with port number if exists */
    if (parse_url($base, PHP_URL_PORT) != ''){
        $abs = "$host:".parse_url($base, PHP_URL_PORT)."$path/$rel";
    }else{
        $abs = "$host$path/$rel";
    }
    /* replace '//' or '/./' or '/foo/../' with '/' */
    $re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#');
    for($n=1; $n>0; $abs=preg_replace($re, '/', $abs, -1, $n)) {}

    /* absolute URL is ready! */
    return $scheme.'://'.$abs;
}

Hope this helps someone!

旧街凉风 2024-10-14 07:36:26

此函数会将相对 URL 解析为 $pgurl给定的当前页面 URL,不使用正则表达式。它成功解析:

/home.php?example 类型、

same-dir nextpage.php 类型、

../...../.../ Parentdir 类型、

完整的 http://example.net url

和速记 //example.net url

//Current base URL (you can dynamically retrieve from $_SERVER)
$pgurl = 'http://example.com/scripts/php/absurl.php';

function absurl($url) {
 global $pgurl;
 if(strpos($url,'://')) return $url; //already absolute
 if(substr($url,0,2)=='//') return 'http:'.$url; //shorthand scheme
 if($url[0]=='/') return parse_url($pgurl,PHP_URL_SCHEME).'://'.parse_url($pgurl,PHP_URL_HOST).$url; //just add domain
 if(strpos($pgurl,'/',9)===false) $pgurl .= '/'; //add slash to domain if needed
 return substr($pgurl,0,strrpos($pgurl,'/')+1).$url; //for relative links, gets current directory and appends new filename
}

function nodots($path) { //Resolve dot dot slashes, no regex!
 $arr1 = explode('/',$path);
 $arr2 = array();
 foreach($arr1 as $seg) {
  switch($seg) {
   case '.':
    break;
   case '..':
    array_pop($arr2);
    break;
   case '...':
    array_pop($arr2); array_pop($arr2);
    break;
   case '....':
    array_pop($arr2); array_pop($arr2); array_pop($arr2);
    break;
   case '.....':
    array_pop($arr2); array_pop($arr2); array_pop($arr2); array_pop($arr2);
    break;
   default:
    $arr2[] = $seg;
  }
 }
 return implode('/',$arr2);
}

用法示例:

echo nodots(absurl('../index.html'));

nodots() 必须在 URL 转换为绝对 URL 之后调用。

点函数有点多余,但可读、快速、不使用正则表达式,并且可以解析 99% 的典型 url(如果你想 100% 确定,只需扩展开关块以支持 6 个以上的点,尽管我从来没有在 URL 中见过这么多点)。

希望这有帮助,

This function will resolve relative URL's to a given current page url in $pgurl without regex. It successfully resolves:

/home.php?example types,

same-dir nextpage.php types,

../...../.../parentdir types,

full http://example.net urls,

and shorthand //example.net urls

//Current base URL (you can dynamically retrieve from $_SERVER)
$pgurl = 'http://example.com/scripts/php/absurl.php';

function absurl($url) {
 global $pgurl;
 if(strpos($url,'://')) return $url; //already absolute
 if(substr($url,0,2)=='//') return 'http:'.$url; //shorthand scheme
 if($url[0]=='/') return parse_url($pgurl,PHP_URL_SCHEME).'://'.parse_url($pgurl,PHP_URL_HOST).$url; //just add domain
 if(strpos($pgurl,'/',9)===false) $pgurl .= '/'; //add slash to domain if needed
 return substr($pgurl,0,strrpos($pgurl,'/')+1).$url; //for relative links, gets current directory and appends new filename
}

function nodots($path) { //Resolve dot dot slashes, no regex!
 $arr1 = explode('/',$path);
 $arr2 = array();
 foreach($arr1 as $seg) {
  switch($seg) {
   case '.':
    break;
   case '..':
    array_pop($arr2);
    break;
   case '...':
    array_pop($arr2); array_pop($arr2);
    break;
   case '....':
    array_pop($arr2); array_pop($arr2); array_pop($arr2);
    break;
   case '.....':
    array_pop($arr2); array_pop($arr2); array_pop($arr2); array_pop($arr2);
    break;
   default:
    $arr2[] = $seg;
  }
 }
 return implode('/',$arr2);
}

Usage Example:

echo nodots(absurl('../index.html'));

nodots() must be called after the URL is converted to absolute.

The dots function is kind of redundant, but is readable, fast, doesn't use regex's, and will resolve 99% of typical urls (if you want to be 100% sure, just extend the switch block to support 6+ dots, although I've never seen that many dots in a URL).

Hope this helps,

亢潮 2024-10-14 07:36:26
function url_to_absolute($baseURL, $relativeURL) {  
    $relativeURL_data = parse_url($relativeURL);

    if (isset($relativeURL_data['scheme'])) {
        return $relativeURL;
    }

    $baseURL_data = parse_url($baseURL);

    if (!isset($baseURL_data['scheme'])) {
        return $relativeURL;
    }

    $absoluteURL_data = $baseURL_data;

    if (isset($relativeURL_data['path']) && $relativeURL_data['path']) {
        if (substr($relativeURL_data['path'], 0, 1) == '/') {
            $absoluteURL_data['path'] = $relativeURL_data['path'];
        } else {
            $absoluteURL_data['path'] = (isset($absoluteURL_data['path']) ? preg_replace('#[^/]*$#', '', $absoluteURL_data['path']) : '/') . $relativeURL_data['path'];
        }

        if (isset($relativeURL_data['query'])) {
            $absoluteURL_data['query'] = $relativeURL_data['query'];
        } else if (isset($absoluteURL_data['query'])) {
            unset($absoluteURL_data['query']);
        }
    } else {
        $absoluteURL_data['path'] = isset($absoluteURL_data['path']) ? $absoluteURL_data['path'] : '/';

        if (isset($relativeURL_data['query'])) {
            $absoluteURL_data['query'] = $relativeURL_data['query'];
        } else if (isset($absoluteURL_data['query'])) {
            $absoluteURL_data['query'] = $absoluteURL_data['query'];
        }
    }

    if (isset($relativeURL_data['fragment'])) {
        $absoluteURL_data['fragment'] = $relativeURL_data['fragment'];
    } else if (isset($absoluteURL_data['fragment'])) {
        unset($absoluteURL_data['fragment']);
    }

    $absoluteURL_path = ltrim($absoluteURL_data['path'], '/');
    $absoluteURL_path_parts = array();

    for ($i = 0, $i2 = 0; $i < strlen($absoluteURL_path); $i++) {
        if (isset($absoluteURL_path_parts[$i2])) {
            $absoluteURL_path_parts[$i2] .= $absoluteURL_path[$i];
        } else {
            $absoluteURL_path_parts[$i2] = $absoluteURL_path[$i];
        }

        if ($absoluteURL_path[$i] == '/') {
            $i2++;
        }
    }

    reset($absoluteURL_path_parts);

    while (true) {
        if (rtrim(current($absoluteURL_path_parts), '/') == '.') {
            unset($absoluteURL_path_parts[key($absoluteURL_path_parts)]);

            continue;
        } else if (rtrim(current($absoluteURL_path_parts), '/') == '..') {
            if (prev($absoluteURL_path_parts) !== false) {
                unset($absoluteURL_path_parts[key($absoluteURL_path_parts)]);
            } else {
                reset($absoluteURL_path_parts);
            }

            unset($absoluteURL_path_parts[key($absoluteURL_path_parts)]);

            continue;
        }

        if (next($absoluteURL_path_parts) === false) {
            break;
        }
    }

    $absoluteURL_data['path'] = '/' . implode('', $absoluteURL_path_parts);

    $absoluteURL = isset($absoluteURL_data['scheme']) ? $absoluteURL_data['scheme'] . ':' : '';
    $absoluteURL .= (isset($absoluteURL_data['user']) || isset($absoluteURL_data['host'])) ? '//' : '';
    $absoluteURL .= isset($absoluteURL_data['user']) ? $absoluteURL_data['user'] : '';
    $absoluteURL .= isset($absoluteURL_data['pass']) ? ':' . $absoluteURL_data['pass'] : '';
    $absoluteURL .= isset($absoluteURL_data['user']) ? '@' : '';
    $absoluteURL .= isset($absoluteURL_data['host']) ? $absoluteURL_data['host'] : '';
    $absoluteURL .= isset($absoluteURL_data['port']) ? ':' . $absoluteURL_data['port'] : '';
    $absoluteURL .= isset($absoluteURL_data['path']) ? $absoluteURL_data['path'] : '';
    $absoluteURL .= isset($absoluteURL_data['query']) ? '?' . $absoluteURL_data['query'] : '';
    $absoluteURL .= isset($absoluteURL_data['fragment']) ? '#' . $absoluteURL_data['fragment'] : '';

    return $absoluteURL;
}
function url_to_absolute($baseURL, $relativeURL) {  
    $relativeURL_data = parse_url($relativeURL);

    if (isset($relativeURL_data['scheme'])) {
        return $relativeURL;
    }

    $baseURL_data = parse_url($baseURL);

    if (!isset($baseURL_data['scheme'])) {
        return $relativeURL;
    }

    $absoluteURL_data = $baseURL_data;

    if (isset($relativeURL_data['path']) && $relativeURL_data['path']) {
        if (substr($relativeURL_data['path'], 0, 1) == '/') {
            $absoluteURL_data['path'] = $relativeURL_data['path'];
        } else {
            $absoluteURL_data['path'] = (isset($absoluteURL_data['path']) ? preg_replace('#[^/]*$#', '', $absoluteURL_data['path']) : '/') . $relativeURL_data['path'];
        }

        if (isset($relativeURL_data['query'])) {
            $absoluteURL_data['query'] = $relativeURL_data['query'];
        } else if (isset($absoluteURL_data['query'])) {
            unset($absoluteURL_data['query']);
        }
    } else {
        $absoluteURL_data['path'] = isset($absoluteURL_data['path']) ? $absoluteURL_data['path'] : '/';

        if (isset($relativeURL_data['query'])) {
            $absoluteURL_data['query'] = $relativeURL_data['query'];
        } else if (isset($absoluteURL_data['query'])) {
            $absoluteURL_data['query'] = $absoluteURL_data['query'];
        }
    }

    if (isset($relativeURL_data['fragment'])) {
        $absoluteURL_data['fragment'] = $relativeURL_data['fragment'];
    } else if (isset($absoluteURL_data['fragment'])) {
        unset($absoluteURL_data['fragment']);
    }

    $absoluteURL_path = ltrim($absoluteURL_data['path'], '/');
    $absoluteURL_path_parts = array();

    for ($i = 0, $i2 = 0; $i < strlen($absoluteURL_path); $i++) {
        if (isset($absoluteURL_path_parts[$i2])) {
            $absoluteURL_path_parts[$i2] .= $absoluteURL_path[$i];
        } else {
            $absoluteURL_path_parts[$i2] = $absoluteURL_path[$i];
        }

        if ($absoluteURL_path[$i] == '/') {
            $i2++;
        }
    }

    reset($absoluteURL_path_parts);

    while (true) {
        if (rtrim(current($absoluteURL_path_parts), '/') == '.') {
            unset($absoluteURL_path_parts[key($absoluteURL_path_parts)]);

            continue;
        } else if (rtrim(current($absoluteURL_path_parts), '/') == '..') {
            if (prev($absoluteURL_path_parts) !== false) {
                unset($absoluteURL_path_parts[key($absoluteURL_path_parts)]);
            } else {
                reset($absoluteURL_path_parts);
            }

            unset($absoluteURL_path_parts[key($absoluteURL_path_parts)]);

            continue;
        }

        if (next($absoluteURL_path_parts) === false) {
            break;
        }
    }

    $absoluteURL_data['path'] = '/' . implode('', $absoluteURL_path_parts);

    $absoluteURL = isset($absoluteURL_data['scheme']) ? $absoluteURL_data['scheme'] . ':' : '';
    $absoluteURL .= (isset($absoluteURL_data['user']) || isset($absoluteURL_data['host'])) ? '//' : '';
    $absoluteURL .= isset($absoluteURL_data['user']) ? $absoluteURL_data['user'] : '';
    $absoluteURL .= isset($absoluteURL_data['pass']) ? ':' . $absoluteURL_data['pass'] : '';
    $absoluteURL .= isset($absoluteURL_data['user']) ? '@' : '';
    $absoluteURL .= isset($absoluteURL_data['host']) ? $absoluteURL_data['host'] : '';
    $absoluteURL .= isset($absoluteURL_data['port']) ? ':' . $absoluteURL_data['port'] : '';
    $absoluteURL .= isset($absoluteURL_data['path']) ? $absoluteURL_data['path'] : '';
    $absoluteURL .= isset($absoluteURL_data['query']) ? '?' . $absoluteURL_data['query'] : '';
    $absoluteURL .= isset($absoluteURL_data['fragment']) ? '#' . $absoluteURL_data['fragment'] : '';

    return $absoluteURL;
}
街角迷惘 2024-10-14 07:36:26

您可以使用此作曲家包来做到这一点。
https://packagist.org/packages/wa72/url

作曲家需要 wa72/url

  • 将 URL 字符串解析为对象

  • 添加和修改查询参数

  • 设置和修改url的任何部分

  • 测试 URL 与 PHP 风格的查询参数的相等性
    方式

  • 支持协议相关的 url

  • 将绝对、主机相对和协议相对 url 转换为
    相对,反之亦然

You can use this composer package to do that.
https://packagist.org/packages/wa72/url

composer require wa72/url

  • Parse URL strings to objects

  • add and modify query parameters

  • set and modify any part of the url

  • test for equality of URLs with query parameters in a PHP-fashioned
    way

  • supports protocol-relative urls

  • convert absolute, host-relative and protocol-relative urls to
    relative and vice versa

终止放荡 2024-10-14 07:36:26

这符合 @jordansstephens 的答案,不支持以“//”开头的绝对 url。

function rel2abs($rel, $base)
{
    /* return if already absolute URL */
    if (parse_url($rel, PHP_URL_SCHEME) != '') return $rel;

    /* Url begins with // */
    if($rel[0] == '/' && $rel[1] == '/'){
        return 'https:' . $rel;
    }

    /* queries and anchors */
    if ($rel[0]=='#' || $rel[0]=='?') return $base.$rel;

    /* parse base URL and convert to local variables:
       $scheme, $host, $path */
    extract(parse_url($base));

    /* remove non-directory element from path */
    $path = preg_replace('#/[^/]*$#', '', $path);

    /* destroy path if relative url points to root */
    if ($rel[0] == '/') $path = '';

    /* dirty absolute URL */
    $abs = "$host$path/$rel";

    /* replace '//' or '/./' or '/foo/../' with '/' */
    $re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#');
    for($n=1; $n>0; $abs=preg_replace($re, '/', $abs, -1, $n)) {}

    /* absolute URL is ready! */
    return $scheme.'://'.$abs;
}

This make suit of @jordansstephens's answer that doesn't support absolute url begins with '//'.

function rel2abs($rel, $base)
{
    /* return if already absolute URL */
    if (parse_url($rel, PHP_URL_SCHEME) != '') return $rel;

    /* Url begins with // */
    if($rel[0] == '/' && $rel[1] == '/'){
        return 'https:' . $rel;
    }

    /* queries and anchors */
    if ($rel[0]=='#' || $rel[0]=='?') return $base.$rel;

    /* parse base URL and convert to local variables:
       $scheme, $host, $path */
    extract(parse_url($base));

    /* remove non-directory element from path */
    $path = preg_replace('#/[^/]*$#', '', $path);

    /* destroy path if relative url points to root */
    if ($rel[0] == '/') $path = '';

    /* dirty absolute URL */
    $abs = "$host$path/$rel";

    /* replace '//' or '/./' or '/foo/../' with '/' */
    $re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#');
    for($n=1; $n>0; $abs=preg_replace($re, '/', $abs, -1, $n)) {}

    /* absolute URL is ready! */
    return $scheme.'://'.$abs;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文