href src と base url がより複雑になり始めたとき、受け入れられた回答ソリューションがうまくいかないことがわかりました。
例えば:
ベース URL:
http://www.journalofadvertisingresearch.com/ArticleCenter/default.asp?ID=86411&Type=記事
href ソース:
/ArticleCenter/LeftMenu.asp?Type=Article&FN=&ID=86411&Vol=&No=&Year=&Any=
誤って返された:
/ArticleCenter/LeftMenu.asp?Type=Article&FN=&ID=86411&Vol=&No=&Year=&Any=
URLを正しく返す以下の関数を見つけました。これは、 Isaac Z. Schlueterのhttp://php.net/manual/en/function.realpath.phpのコメントから入手しました。
これは正しく返されました:
http://www.journalofadvertisingresearch.com/ArticleCenter/LeftMenu.asp?Type=Article&FN=&ID=86411&Vol=&No=&Year=&Any=
function resolve_href ($base, $href) {
// href="" ==> current url.
if (!$href) {
return $base;
}
// href="http://..." ==> href isn't relative
$rel_parsed = parse_url($href);
if (array_key_exists('scheme', $rel_parsed)) {
return $href;
}
// add an extra character so that, if it ends in a /, we don't lose the last piece.
$base_parsed = parse_url("$base ");
// if it's just server.com and no path, then put a / there.
if (!array_key_exists('path', $base_parsed)) {
$base_parsed = parse_url("$base/ ");
}
// href="/ ==> throw away current path.
if ($href{0} === "/") {
$path = $href;
} else {
$path = dirname($base_parsed['path']) . "/$href";
}
// bla/./bloo ==> bla/bloo
$path = preg_replace('~/\./~', '/', $path);
// resolve /../
// loop through all the parts, popping whenever there's a .., pushing otherwise.
$parts = array();
foreach (
explode('/', preg_replace('~/+~', '/', $path)) as $part
) if ($part === "..") {
array_pop($parts);
} elseif ($part!="") {
$parts[] = $part;
}
return (
(array_key_exists('scheme', $base_parsed)) ?
$base_parsed['scheme'] . '://' . $base_parsed['host'] : ""
) . "/" . implode("/", $parts);
}