Мне нужна функция, которая задает относительный URL-адрес, а база возвращает абсолютный URL-адрес. Я искал и нашел множество функций, которые делают это по-разному.
resolve("../abc.png", "http://example.com/path/thing?foo=bar") # returns http://example.com/abc.png
Есть ли канонический путь?
На этом сайте я вижу отличные примеры для python и c #, позволяет получить решение PHP.
Возможно, эта статья может помочь?
http: // nashruddin.com/PHP_Script_for_Converting_Relative_to_Absolute_URL
Изменить: воспроизведен код ниже для удобства
<?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; } ?>
Если у вас есть pecl-http, вы можете использовать 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);
Пример:
<?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://img.ruphp.com/url/pic.jpg echo getAbsoluteURL('http://foo.tw/a/b/c/', '../pic.jpg') . "\n"; // http://img.ruphp.com/url/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
другие инструменты, которые уже связаны на странице, связанной с комментарием pguardiario: http://publicmind.in/blog/urltoabsolute/ , https://github.com/monkeysuffrage/phpuri .
и я нашел другой инструмент из комментария в 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.
Вот еще одна функция, которая может обрабатывать относительные URL-адреса протокола
<?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";
Я заметил, что вышеприведенный ответ использует RegEx, что может быть опасно при работе с URL-адресами.
Эта функция будет разрешать относительные URL-адреса для заданного текущего URL-адреса страницы в $pgurl
без регулярного выражения . Он успешно решает:
/home.php?example
типы,
такие же типы nextpage.php
,
../...../.../parentdir
,
полные URL-адреса http://example.net
,
и сокращенные URL-адреса //example.net
//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 в абсолютный.
Функция точек является излишней, но читается, быстро, не использует регулярные выражения и будет разрешать 99% типичных URL-адресов (если вы хотите быть на 100% уверенным, просто расширяйте блок переключателей, чтобы поддерживать 6+ точек, хотя Я никогда не видел столько точек в URL-адресе).
Надеюсь это поможет,