PHP: comment résoudre une url relative

j'ai besoin d'une fonction qui donne une URL relative et une base renvoie une URL absolue. J'ai cherché et trouvé de nombreuses fonctions qui le font de différentes façons.

resolve("../abc.png", "http://example.com/path/thing?foo=bar")
# returns http://example.com/abc.png

y a-t-il un moyen canonique?

sur ce site je vois de grands exemples pour python et c#, permet d'obtenir une solution PHP.

22
demandé sur Paul Tarjan 2009-08-07 11:25:22

6 réponses

peut-être que cet article pourrait aider?

http:// nashruddin.com/PHP_Script_for_Converting_Relative_to_Absolute_URL

Edit: code reproduit ci-dessous pour plus de commodité

<?php
    function rel2abs($rel, $base)
    {
        /* return if already absolute URL */
        if (parse_url($rel, PHP_URL_SCHEME) != '' || substr($rel, 0, 2) == '//') 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;
    }
?>
8
répondu Amber 2016-02-22 13:12:28

si vous avez pecl-http, vous pouvez utiliser http://php.net/manual/en/function.http-build-url.php

<?php
$url_parts = parse_url($relative_url);
$absolute = http_build_url($source_url, $url_parts, HTTP_URL_JOIN_PATH);

Ex:

<?php
function getAbsoluteURL($source_url, $relative_url)
{
    $url_parts = parse_url($relative_url);
    return http_build_url($source_url, $url_parts, HTTP_URL_JOIN_PATH);
}
echo getAbsoluteURL('http://foo.tw/a/b/c', '../pic.jpg') . "\n";
// http://foo.tw/a/pic.jpg

echo getAbsoluteURL('http://foo.tw/a/b/c/', '../pic.jpg') . "\n";
// http://foo.tw/a/b/pic.jpg

echo getAbsoluteURL('http://foo.tw/a/b/c/', 'http://bar.tw/a.js') . "\n";
// http://bar.tw/a.js

echo getAbsoluteURL('http://foo.tw/a/b/c/', '/robots.txt') . "\n";
// http://foo.tw/robots.txt
4
répondu Ronny Wang 2012-05-18 06:11:34

autres outils qui sont déjà liés dans la page liée dans le commentaire de pguardiario: http://publicmind.in/blog/urltoabsolute / , https://github.com/monkeysuffrage/phpuri .

et j'ai trouvé un autre outil de commentaire dans http://nadeausoftware.com/articles/2008/05/php_tip_how_convert_relative_url_absolute_url :

require_once 'Net/URL2.php';
$base = new Net_URL2('http://example.org/foo.html');
$absolute = (string)$base->resolve('relative.html#bar'); 
1
répondu qdinar 2016-01-04 08:12:48

Voici une autre fonction qui peut gérer les urls relatives au protocole

<?php
function getAbsoluteURL($to, $from = null) {
    $arTarget = parse_url($to);
    $arSource = parse_url($from);
    $targetPath = isset($arTarget['path']) ? $arTarget['path'] : '';

    if (isset($arTarget['host'])) {
        if (!isset($arTarget['scheme'])) {
            $proto = isset($arSource['scheme']) ? "{$arSource['scheme']}://" : '//';
        } else {
            $proto = "{$arTarget['scheme']}://";
        }
        $baseUrl = "{$proto}{$arTarget['host']}" . (isset($arTarget['port']) ? ":{$arTarget['port']}" : '');
    } else {
        if (isset($arSource['host'])) {
            $proto = isset($arSource['scheme']) ? "{$arSource['scheme']}://" : '//';
            $baseUrl = "{$proto}{$arSource['host']}" . (isset($arSource['port']) ? ":{$arSource['port']}" : '');
        } else {
            $baseUrl = '';
        }
        $arPath = [];

        if ((empty($targetPath) || $targetPath[0] !== '/') && !empty($arSource['path'])) {
            $arTargetPath = explode('/', $targetPath);
            if (empty($arSource['path'])) {
                $arPath = [];
            } else {
                $arPath = explode('/', $arSource['path']);
                array_pop($arPath);
            }
            $len = count($arPath);
            foreach ($arTargetPath as $idx => $component) {
                if ($component === '..') {
                    if ($len > 1) {
                        $len--;
                        array_pop($arPath);
                    }
                } elseif ($component !== '.') {
                    $len++;
                    array_push($arPath, $component);
                }
            }
            $targetPath = implode('/', $arPath);
        }
    }

    return $baseUrl . $targetPath;
}

// SAMPLES
// Absolute path => https://www.google.com/doubleclick/
echo getAbsoluteURL('/doubleclick/', 'https://www.google.com/doubleclick/insights/') . "\n";
// Relative path 1 => https://www.google.com/doubleclick/studio
echo getAbsoluteURL('../studio', 'https://www.google.com/doubleclick/insights/') . "\n";
// Relative path 2 => https://www.google.com/doubleclick/insights/case-studies.html
echo getAbsoluteURL('./case-studies.html', 'https://www.google.com/doubleclick/insights/') . "\n";
// Relative path 3 => https://www.google.com/doubleclick/insights/case-studies.html
echo getAbsoluteURL('case-studies.html', 'https://www.google.com/doubleclick/insights/') . "\n";
// Protocol relative url => https://www.google.com/doubleclick/
echo getAbsoluteURL('//www.google.com/doubleclick/', 'https://www.google.com/doubleclick/insights/') . "\n";
// Empty path => https://www.google.com/doubleclick/insights/
echo getAbsoluteURL('', 'https://www.google.com/doubleclick/insights/') . "\n";
// Different url => http://www.yahoo.com/
echo getAbsoluteURL('http://www.yahoo.com/', 'https://www.google.com') . "\n";
1
répondu Joyce Babu 2018-04-05 11:31:42
function absoluteUri($Path, $URI)
{   # Requires PHP4 or better.
    $URL = parse_url($URI);
    $Str = "{$URL['scheme']}://";

    if (isset($URL['user']) || isset($URL['pass']))
        $Str .= "{$URL['user']}:{$URL['pass']}@";

    $Str .= $URL['host'];

    if (isset($URL['port']))
        $Str .= ":{$URL['port']}";

    $Str .= realpath($URL['path'] . $Path); # This part might have an issue on windows boxes.

    if (isset($URL['query']))
        $Str .= "?{$URL['query']}";

    if (isset($URL['fragment']))
        $Str .= "#{$URL['fragment']}";

    return $Str;
}

absoluteUri("../abc.png", "http://example.com/path/thing?foo=bar");
# Should return "http://example.com/abc.png?foo=bar" on Linux boxes.
0
répondu Mark Tomlin 2011-09-09 13:24:51

j'ai remarqué que la réponse mentionnée ci-dessus utilise RegEx, ce qui peut être dangereux lorsqu'on traite avec des URLs.

cette fonction résoudra les URL relatives à un donné l'url de la page courante dans $pgurl sans regex . Il résout avec succès:

/home.php?example types,

same-dir nextpage.php types,

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

plein http://example.net url,

et l'abréviation //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);
}

Exemple D'Utilisation:

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

nodots() doit être appelé après L'URL est convertie en absolu.

la fonction dots est en quelque sorte redondante, mais est lisible, rapide, n'utilise pas regex, et résoudra 99% des urls typiques (si vous voulez être sûr à 100%, il suffit d'étendre le commutateur bloc à l'appui de+ de 6 points, bien que je n'ai jamais vu que de nombreux points dans une URL).

Espère que cette aide,

-1
répondu Aaron Gillion 2016-04-18 19:42:11