在PHP中转换相对于绝对路径的帖子很多。我正在寻找超出这些帖子的具体实现(希望如此)。有谁可以帮我解决这个具体的实施?
我有一个包含各种HTML的PHP变量,包括包含相对网址的href
和img
。主要是(例如)/en/discover
或/img/icons/facebook.png
我想以这样一种方式处理这个PHP变量,即我的href
和img
的值将转换为http://mydomain.com/en/discover
和http://mydomain.com/img/icons/facebook.png
我认为下面的问题涵盖了href
的解决方案。我们如何扩展它以考虑img
s?
正则表达式是否正常?或者,因为我们处理大量输出应该使用DOMDocument吗?
答案 0 :(得分:8)
经过一些进一步的研究后,我偶然发现了Gerd Riesselmann关于如何解决缺少base href
RSS-feeds解决方案的文章。 他的片段实际上解决了我的问题!
http://www.gerd-riesselmann.net/archives/2005/11/rss-doesnt-know-a-base-url
<?php
function relToAbs($text, $base)
{
if (empty($base))
return $text;
// base url needs trailing /
if (substr($base, -1, 1) != "/")
$base .= "/";
// Replace links
$pattern = "/<a([^>]*) " .
"href=\"[^http|ftp|https|mailto]([^\"]*)\"/";
$replace = "<a\${1} href=\"" . $base . "\${2}\"";
$text = preg_replace($pattern, $replace, $text);
// Replace images
$pattern = "/<img([^>]*) " .
"src=\"[^http|ftp|https]([^\"]*)\"/";
$replace = "<img\${1} src=\"" . $base . "\${2}\"";
$text = preg_replace($pattern, $replace, $text);
// Done
return $text;
}
?>
谢谢Gerd!谢谢shadyyx指出我base href
的方向!
答案 1 :(得分:4)
出色的解决方案。 但是,模式中存在一个小错字。如上所述,它会截断href或src的第一个字符。以下是符合预期的模式:
// Replace links
$pattern = "/<a([^>]*) " .
"href=\"([^http|ftp|https|mailto][^\"]*)\"/";
和
// Replace images
$pattern = "/<img([^>]*) " .
"src=\"([^http|ftp|https][^\"]*)\"/";
移动第二个替换引用的左括号。这会将href或src的第一个字符与http | ftp | https不匹配到替换引用中。
答案 2 :(得分:2)
我发现当href src和base url开始变得越来越复杂时,接受的答案解决方案对我来说并不起作用。
例如:
基本网址:
http://www.journalofadvertisingresearch.com/ArticleCenter/default.asp?ID=86411&Type=Article
href src:
/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的以下函数。我在这里发表评论:http://php.net/manual/en/function.realpath.php来自Isaac Z. Schlueter。
这已正确返回:
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);
}