[英]Relative + base URL to absolute URL?
基本上,給定基本網址,例如
file:///path/to/some/file.html
以及相對網址
another_file.php?id=5
我要出去
file:///path/to/some/another_file.php?id=5
我發現這個腳本 (這是一樣的這一個 ),但它似乎並沒有在工作file://
方案。 在使用我的代碼之前,我正在做一些本地測試,所以我想同時使用file://
和http://
。
有人知道將執行此操作的腳本/功能嗎?
在C#中,我將使用Uri(Uri base,string rel) 。
以上僅是示例。 它可以在您可以放入<a href="xxx">
任何 URL上<a href="xxx">
。
這是到目前為止我所能獲得的最好的結果,但是它無法處理..
以及其他一些事情:
function rel2abs($base, $rel) {
if (parse_url($rel, PHP_URL_SCHEME) != '') return $rel;
if ($rel[0]=='#' || $rel[0]=='?') return $base.$rel;
$parse = parse_url($base);
$path = preg_replace('#/[^/]*$#', '', $parse['path']);
if ($rel[0] == '/') $path = '';
$abs = (isset($path['host'])?$path['host']:'')."$path/$rel";
$re = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#');
for($n=1; $n>0; $abs=preg_replace($re, '/', $abs, -1, $n)) {}
return $parse['scheme'].'://'.$abs;
}
您可以使用parse_url()將URL分成多個部分,然后在正斜杠字符上拆分“路徑”部分。 那應該允許您重新組裝它們並替換最后一部分。
像這樣的東西(偽代碼,未經測試,不確定它是否有效的PHP語法):
$url_parts = parse_url($url_text);
$path_parts = explode('/', $url_parts[path]);
$new_url = $url_parts[scheme] + ":";
if ($url_parts[scheme] == "file") {
$new_url .= '///';
} else {
$new_url .= '//';
}
$new_url .= $url_parts[hostname] . '/';
for (int i = 0; i < count($path_parts) - 1; i++) {
$new_url .= $path_parts[i] . "/";
}
$new_url .= $REPLACEMENT_FILENAME
如果需要,您可以在末尾附加查詢字符串和/或錨定片段(以#開頭)-有關該數組中URL部分的列表,請參見parse_url()手冊頁。
我已經修改了Puggan Se的答案,以處理HTML頁面中看到的某些相對URL。
function url2absolute($baseurl, $relativeurl) {
// if the relative URL is scheme relative then treat it differently
if(substr($relativeurl, 0, 2) === "//") {
if(parse_url($baseurl, PHP_URL_SCHEME) != null) {
return parse_url($baseurl, PHP_URL_SCHEME) . ":" . $relativeurl;
} else { // assume HTTP
return "http:" . $relativeurl;
}
}
// if the relative URL points to the root then treat it more simply
if(substr($relativeurl, 0, 1) === "/") {
$parts = parse_url($baseurl);
$return = $parts['scheme'] . ":";
$return .= ($parts['scheme'] === "file") ? "///" : "//";
// username:password@host:port ... could go here too!
$return .= $parts['host'] . $relativeurl;
return $return;
}
// If the relative URL is actually an absolute URL then just use that
if(parse_url($relativeurl, PHP_URL_SCHEME) !== null) {
return $relativeurl;
}
$parts = parse_url($baseurl);
// Chop off the query string in a base URL if it is there
if(isset($parts['query'])) {
$baseurl = strstr($baseurl,'?',true);
}
// The rest is adapted from Puggan Se
$return = ""; // string to return at the end
$minpartsinfinal = 3; // for everything except file:///
if($parts['scheme'] === "file") {
$minpartsinfinal = 4;
}
// logic for username:password@host:port ... query string etc. could go here too ... somewhere?
$basepath = explode('/', $baseurl); // will this handle correctly when query strings have '/'
$relpath = explode('/', $relativeurl);
array_pop($basepath);
$returnpath = array_merge($basepath, $relpath);
$returnpath = array_reverse($returnpath);
$parents = 0;
foreach($returnpath as $part_nr => $part_value) {
/* if we find '..', remove this and the next element */
if($part_value == '..') {
$parents++;
unset($returnpath[$part_nr]);
} /* if we find '.' remove this element */
else if($part_value == '.') {
unset($returnpath[$part_nr]);
} /* if this is a normal element, and we have unhandled '..', then remove this */
else if($parents > 0) {
unset($returnpath[$part_nr]);
$parents--;
}
}
$returnpath = array_reverse($returnpath);
if(count($returnpath) < $minpartsinfinal) {
return FALSE;
}
return implode('/', $returnpath);
}
例子:
print url2absolute("file:///path/to/some/file.html", "another_file.php?id=5") . "<br>"; // original example
print url2absolute("file:///path/to/some/file.html", "../../../../../another_file.php?id=5") . "<br>"; // should be an error!
print url2absolute("http://path/to/some/file.html?source=this/one", "another_file.php?id=5") . "<br>"; // with query string on base URL
print url2absolute("http://path/to/some/file.html", "//other-path/another_file.php?id=5") . "<br>"; // scheme relative
<?php
/* strings from your exemple */
$base_url = "file:///path/to/some/file.html";
$relative_url = "another_file.php?id=5";
/* split up urls folder parts into an array */
$base_url_parts = explode('/', $base_url);
$relative_parts = explode('/', $relative);
/* remove last element (in this case "file.html") */
array_pop($base_url_parts);
/* merge absolute_url from base and relative */
$absolute_url_parts = array_merge($base_url_parts, $relative_parts);
/* reverser the list before the search of '..' */
$absolute_url_parts = array_reverse($absolute_url_parts);
/* count of current number of unhandled '..' */
$parent_folder_count = 0;
/* loop throught all elements looking for '..' */
foreach($absolute_url_parts as $part_nr => $part_value)
{
/* if we find '..', remove this and the next element */
if($part_value = '..')
{
$parent_folder_count++;
unset($absolute_url_parts[$part_nr]);
}
/* if we find '.' remove this element */
else if($part_value = '.')
{
unset($absolute_url_parts[$part_nr]);
}
/* if this is a normal element, and we have unhandled '..', then remove this */
else if($parent_folder_count > 0)
{
unset($absolute_url_parts[$part_nr]);
$parent_folder_count--;
}
/* else: keep it */
}
/* restore the order by reversing again */
$absolute_url_parts = array_reverse($absolute_url_parts);
/* restore the list to a string again */
$absolute_url = implode('/', $absolute_url_parts);
/* done */
?>
我認為最簡單的解決方案是使用dirname()函數。
$url = 'file:///path/to/some/file.html';
$rel = 'another_file.php?id=5';
$final = dirname($url).'/'.$rel;
$ab="file:///path/to/some/file.html";
$rel="another_file.php?id=5";
$exab=explode("/",$ab);
$exab[count($exab)-1]=$rel;
$newab=implode("/",$exab);
可能不是最優雅的解決方案,但它可行。
$file1 = "file://path/to/some/file.html";
$file2 = "anotherfile?q=1";
$newurl = substr_replace($file1, $file2, strrpos($file1, "/")+1);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.