Допустим, у меня есть URL документа, ссылающегося на другой документ (который может быть как абсолютным, так и относительным), и мне нужно, чтобы эта ссылка была абсолютной.
Я сделал простую функцию, обеспечивающую эту функциональность для нескольких распространенных случаев:
function absolute_url($url,$parent_url){
$parent_url=parse_url($parent_url);
if(strcmp(substr($url,0,7),'http://')==0){
return $url;
}
elseif(strcmp(substr($url,0,1),'/')==0){
return $parent_url['scheme']."://".$parent_url['host'].$url;
}
else{
$path=$parent_url['path'];
$path=substr($path,0,strrpos($path,'/'));
return $parent_url['scheme']."://".$parent_url['host']."$path/".$url;
}
}
$parent_url='http://example.com/path/to/file/name.php?abc=abc';
echo absolute_url('name2.php',$parent_url)."\n";
// output http://example.com/path/to/file/name2.php
echo absolute_url('/name2.php',$parent_url)."\n";
// output http://example.com/name2.php
echo absolute_url('http://name2.php',$parent_url)."\n";
// output http://name2.php
Код работает нормально, но может быть больше таких случаев, как ../../path/to/file.php
который не будет работать.
Так есть ли какие-нибудь стандартные классы или функции, делающие эту вещь лучше (более универсальной), чем моя функция?
Я попытался Google это и проверить подобные вопросы (один а также два) но это похоже на решение, связанное с серверным путем, которое я не ищу.
Эта функция преобразует относительные URL в дано URL текущей страницы в $pgurl
без регулярных выражений. Это успешно решает:
/home.php?example
типы,
то же самое, реж nextpage.php
типы,
../...../.../parentdir
типы,
полный http://example.net
URLs,
и стенография //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);
}
Пример использования:
echo nodots(absurl('../index.html'));
nodots()
должен быть назван после URL-адрес преобразуется в абсолютный.
Функция многоточия отчасти избыточна, но является читаемой, быстрой, не использует регулярные выражения и разрешит 99% типичных URL-адресов (если вы хотите быть на 100% уверенными, просто расширьте блок переключателя, чтобы поддерживать более 6 точек, хотя Я никогда не видел столько точек в URL).
Надеюсь это поможет,
$uri = "..";
$path = realpath($uri);
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
if($path){
$path = str_replace($root, "", $path);
$path = $_SERVER["SERVER_NAME"] . $path;
$protocol = "http";
if(isset($_SERVER["HTTPS"])){
$protocol .= "s";
}
$path = "{$protocol}://$path";
$path = str_replace("\\", "/", $path);
}
var_dump($path);
Есть, вероятно, лучший / более быстрый способ, но я только что выбил это …