2009-08-07 14 views
22

Ho bisogno di una funzione che abbia un URL relativo e una base restituisca un URL assoluto. Ho cercato e trovato molte funzioni che lo fanno in modi diversi.PHP: Come risolvere un url relativo

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

Esiste un modo canonico?

In questo sito vedo ottimi esempi per python e C#, consente di ottenere una soluzione PHP.

+2

Ecco [un confronto] (http://scraperblog.blogspot.com/2012/12/convert- relative-urls-to-absolute-in.html) di alcune delle soluzioni menzionate più una delle mie. – pguardiario

+0

Questo codice ha fatto il trucco per me: http://sourceforge.net/projects/absoluteurl/ –

+0

dublicates: http://stackoverflow.com/questions/4444475/transfrom-relative-path-into-absolute-url-using -php http://stackoverflow.com/questions/11653677/php-relative-urls-to-absolute-urls-conversion-with-eventually-base-href-html-tag http://stackoverflow.com/questions/19618754/convert-relative-url-url-assoluto- http://stackoverflow.com/questions/26423904/converting-relative-url-to-solutions – qdinar

risposta

8

Forse questo articolo potrebbe aiutare?

http: // nashruddin.com/PHP_Script_for_Converting_Relative_to_Absolute_URL

Edit: riprodotto codice qui sotto per comodità

<?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; 
    } 
?> 
+0

Questa implementazione non funziona se l'URL di base è: http://foobar.com Senza trailing /. Inoltre, non rispetta i numeri di porta negli URL di base. –

+2

È in base alla progettazione che ignora le specifiche RFC che sono comunque in uso. Direi che è una supposizione *** l'URL assoluto o uno relativo. – hakre

+0

Dominio scaduto. – Pharap

0
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. 
+2

Sulle finestre di Linux ma non su Windows? Questa sembra essere l'unica soluzione finora che non vale nemmeno la pena di prendere in considerazione. – pguardiario

4

Se il tuo hanno PECL-http, è possibile utilizzare 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); 

Es:

<?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 
+1

FYI, il metodo 'http_build_url' fa parte di un'estensione PECL che non è in bundle con PHP. – mpen

+0

Funziona come descritto, ma fai attenzione quando installi l'estensione pecl. La versione 2.0 appena rilasciata ora utilizza gli spazi dei nomi e non fornisce direttamente questa funzione. Così ho installato una versione precedente e funziona perfettamente per me: 'pecl install pecl_http-1.7.6' – KTB

-1

ho notato la risposta upvoted precedente utilizza RegEx, che può essere pericoloso quando si tratta di URL.

Questa funzione risolverà URL relativi ad un determinato pagina corrente url nella $pgurlsenza regex. Si risolve con successo:

/home.php?example tipi,

stessi-dir nextpage.php tipi,

../...../.../parentdir tipi,

pieni http://example.net gli URL,

e stenografia //example.net gli 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); 
} 

Uso Esempio:

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

nodots() deve essere chiamato dopo l'URL viene convertito in assoluto.

La funzione punti è una sorta di ridondante, ma è leggibile, veloce, non usa regex e risolverà il 99% degli URL tipici (se si vuole essere sicuri al 100%, basta estendere il blocco switch per supportare 6 + punti, anche se non ho mai visto tanti punti in un URL).

Spero che questo aiuti,

0

Ecco un'altra funzione in grado di gestire il protocollo URL relativi

<?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); 
      } 
      foreach ($arTargetPath as $idx => $component) { 
       if ($component === '..' && !empty($arPath)) { 
        array_pop($arPath); 
       } else if ($component !== '.') { 
        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";