PHP:在输出中查找具有相对路径的图像和链接,并将它们转换为绝对路径

时间:2012-11-19 16:09:47

标签: php image relative-path src absolute-path

在PHP中转换相对于绝对路径的帖子很多。我正在寻找超出这些帖子的具体实现(希望如此)。有谁可以帮我解决这个具体的实施?

我有一个包含各种HTML的PHP​​变量,包括包含相对网址的hrefimg。主要是(例如)/en/discover/img/icons/facebook.png

我想以这样一种方式处理这个PHP变量,即我的hrefimg的值将转换为http://mydomain.com/en/discoverhttp://mydomain.com/img/icons/facebook.png

我认为下面的问题涵盖了href的解决方案。我们如何扩展它以考虑img s?

正则表达式是否正常?或者,因为我们处理大量输出应该使用DOMDocument吗?

3 个答案:

答案 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); 
}