2009-08-07 15 views
22

Necesito una función que, dada una URL relativa y una base, devuelva una URL absoluta. He buscado y encontré muchas funciones que lo hacen de diferentes maneras.PHP: cómo resolver una URL relativa

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

¿Hay alguna manera canónica?

En este sitio veo excelentes ejemplos para Python y C#, obtengamos una solución de PHP.

+2

Aquí es [una comparación] (http://scraperblog.blogspot.com/2012/12/convert- relative-urls-to-absolute-in.html) de algunas de las soluciones mencionadas más una mía propia. – pguardiario

+0

Este código me funcionó: 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-to-absolute-url http://stackoverflow.com/questions/26423904/converting-relative-url-to-absolute – qdinar

Respuesta

8

Quizás este artículo podría ayudar?

http: // nashruddin.com/PHP_Script_for_Converting_Relative_to_Absolute_URL

Editar: Código reproduce a continuación por conveniencia

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

Esta implementación no funciona si la URL base es: http://foobar.com Sin seguimiento /. Tampoco respeta los números de puerto en las URL base. –

+2

Es, por diseño, ignorar las especificaciones de RFC que están en uso para eso de todos modos. Diría que está *** adivinando *** la URL absoluta o relativa. – hakre

+0

Dominio caducado. – 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

¿En linux boxes pero no windows? Esta parece ser la única solución hasta ahora que ni siquiera vale la pena considerar. – pguardiario

4

si su tenga pecl-http, puede utilizar 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); 

Ej:

<?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, el método 'http_build_url' es parte de una extensión PECL que no está incluida con PHP. – mpen

+0

Esto funciona como se describe, pero tenga cuidado al instalar la extensión pecl. La versión 2.0 recientemente lanzada ahora usa espacios de nombres y no proporciona esta función directamente. Así que instalé una versión anterior y funciona perfectamente para mí: 'pecl install pecl_http-1.7.6' – KTB

1

otras herramientas que ya están vinculados en la página del enlace en el comentario de pguardiario: http://publicmind.in/blog/urltoabsolute/, https://github.com/monkeysuffrage/phpuri.

y he encontrado otra herramienta de comentario en 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

me di cuenta de la respuesta upvoted anterior utiliza expresiones regulares, que puede ser peligroso cuando se trata de direcciones URL.

Esta función se resolverá URL relativos a una página actual url dada en $pgurlsin expresiones regulares. Se resuelve con éxito:

/home.php?example tipos,

mismos-dir nextpage.php tipos,

../...../.../parentdir tipos,

completos http://example.net URLs,

y taquigrafía //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); 
} 

Ejemplo de uso:

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

nodots() debe ser llamado después de la URL se convierte en absoluto.

La función de puntos es algo redundante, pero es legible, rápida, no utiliza expresiones regulares, y resolverá el 99% de las URL típicas (si quiere estar 100% seguro, simplemente extienda el bloque de conmutadores para admitir 6 + puntos, aunque nunca he visto tantos puntos en una URL).

Espero que esto ayude,

0

Aquí es otra función que pueda manejar protocolos URL relativos

<?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"; 
Cuestiones relacionadas