php - whatwg - html spec
PHP: cómo resolver una URL relativa (6)
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.
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 #, permite obtener una solución de PHP.
Aquí hay otra función que puede manejar las URL relativas al protocolo
<?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";
Noté que la respuesta arriba expuesta arriba usa RegEx, que puede ser peligroso cuando se trata de URL.
Esta función resolverá las URL relativas a una url de página actual dada en $pgurl
sin expresión regular . Se resuelve con éxito:
/home.php?example
types,
same-dir nextpage.php
tipos,
../...../.../parentdir
tipos,
URL completas de http://example.net
,
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 llamar a nodots()
después de que la URL se convierte a absoluta.
La función de puntos es algo redundante, pero es legible, rápida, no usa expresiones regulares, y resolverá el 99% de las direcciones urls típicas (si quiere estar 100% seguro, simplemente extienda el bloque de conmutadores para admitir más de 6 puntos, aunque Nunca he visto tantos puntos en una URL).
Espero que esto ayude,
Si tiene pecl-http, puede usar 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
Tal vez este artículo podría ayudar?
http: // nashruddin.com/PHP_Script_for_Converting_Relative_to_Absolute_URL
Editar: código reproducido a continuación para mayor comodidad
<?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;
}
?>
otras herramientas que ya están vinculadas en la página vinculada 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'');
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.