9

有很多关于在 PHP 中将相对路径转换为绝对路径的帖子。我正在寻找这些帖子之外的特定实现(希望如此)。有人可以帮我完成这个具体的实现吗?

我有一个包含各种 HTML 的 PHP 变量,包括hrefs 和imgs 包含相对 url。大多数(例如)/en/discover/img/icons/facebook.png

我想以这样的方式处理这个 PHP 变量,我href的 s 和imgs 的值将被转换http://mydomain.com/en/discoverhttp://mydomain.com/img/icons/facebook.png

我相信下面的问题涵盖了hrefs 的解决方案。我们如何将其扩展为也考虑imgs?

正则表达式是否有序?或者既然我们要处理大量的输出,我们应该使用 DOMDocument 吗?

4

3 回答 3

9

经过一些进一步的研究,我偶然发现了 Gerd Riesselmann 的这篇关于如何解决base hrefRSS 提要解决方案缺失的文章。他的片段实际上解决了我的问题!

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;
}
?>

谢谢格德!并感谢 shadyyx 为我指明方向base href

于 2012-11-20T14:04:02.967 回答
4

优秀的解决方案。但是,模式中有一个小错字。如上所述,它会截断 href 或 src 的第一个字符。以下是按预期工作的模式:

// Replace links
$pattern = "/<a([^>]*) " .
         "href=\"([^http|ftp|https|mailto][^\"]*)\"/";

// Replace images
$pattern = "/<img([^>]*) " . 
         "src=\"([^http|ftp|https][^\"]*)\"/";

第二个替换引用的左括号被移动。这会将不匹配 http|ftp|https 的 href 或 src 的第一个字符带入替换引用。

于 2013-05-22T20:53:37.163 回答
3

我发现当 href src 和 base url 开始变得更加复杂时,接受的答案解决方案对我不起作用。

例如:

基本网址:

http://www.journalofadvertisingresearch.com/ArticleCenter/default.asp?ID=86411&Type=Article

参考资料来源:

/ArticleCenter/LeftMenu.asp?Type=文章&FN=&ID=86411&Vol=&No=&Year=&Any=

错误返回:

/ArticleCenter/LeftMenu.asp?Type=文章&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); 
} 
于 2015-07-29T06:49:34.737 回答