【问题标题】:Changing base URL on part of a page only仅更改部分页面的基本 URL
【发布时间】:2012-07-30 08:04:11
【问题描述】:

我的站点上有一个页面,该页面从同一服务器上另一个(旧)站点的数据库中获取并显示新闻项目。某些项目包含相对链接,应予以修复,以便它们直接指向外部站点,而不是在主站点上导致 404 错误。

我最初考虑在获取的新闻项目上使用<base> 标签,但这会改变整个页面的基本 URL,破坏主导航中的相对链接 - 而且感觉也很hackish。

我目前正在考虑创建一个正则表达式来查找相对 URL(它们都以 /index.php? 开头)并在它们前面加上所需的基本 URL。有没有更优雅的解决方案?该站点基于 Symfony 2 构建并使用 jQuery。

【问题讨论】:

  • 您的新网站没有/index.php 文件吗?如果没有,为什么不创建一个并将这些行放入其中:header("{$_SERVER['SERVER_PROTOCOL']} 301 Moved Permanently"); header('Location: http://othersite.tld/index.php?'.http_build_query($_GET)); - 这样您根本不必修改新站点上的输出。此外,如果您不能/不想这样做,您说您是从数据库获取数据 - 您是获取 URL 作为原始数据,还是获取预构建的 HTML?
  • @DaveRandom:不幸的是,当前站点确实有一个/index.php,并且数据库中的数据是预构建的 HTML。
  • 好吧,至少你已经让它具有挑战性了。我们在谈论多少 HTML?我们都知道建议在 SO 上做任何与 HTML/regex 相关的事情的危险(尽管在这种情况下你是在寻找 URL 而不是查看 HTML 本身,所以它可能没问题)但是如果你可以将它加载到 DOM 和 XPath 中带有src/href 属性的元素会更好。是一大堆小块,一大块还是介于两者之间?
  • @DaveRandom:这是几千块,每块几千字节。一次只显示一个,但越亮越好。
  • 只批量更新数据库是否可以接受?这将是最好的方法。它可以在每次页面加载时即时完成,但这会增加页面加载时间的宝贵毫秒......

标签: php html url symfony relative-path


【解决方案1】:

我将如何解决这个问题:

function prepend_url ($prefix, $path) {
    // Prepend $prefix to $path if $path is not a full URL
    $parts = parse_url($path);
    return empty($parts['scheme']) ? rtrim($prefix, '/').'/'.ltrim($path, '/') : $path;
}

// The URL scheme and domain name of the other site
$otherDomain = 'http://othersite.tld';

// Create a DOM object
$dom = new DOMDocument('1.0');
$dom->loadHTML($inHtml); // $inHtml is an HTML string obtained from the database

// Create an XPath object
$xpath = new DOMXPath($dom);

// Find candidate nodes
$nodesToInspect = $xpath->query('//*[@src or @href]');

// Loop candidate nodes and update attributes
foreach ($nodesToInspect as $node) {
    if ($node->hasAttribute('src')) {
        $node->setAttribute('src', prepend_url($otherDomain, $node->getAttribute('src')));
    }
    if ($node->hasAttribute('href')) {
        $node->setAttribute('href', prepend_url($otherDomain, $node->getAttribute('href')));
    }
}

// Find all nodes to export
$nodesToExport = $xpath->query('/html/body/*');

// Iterate and stringify them
$outHtml = '';
foreach ($nodesToExport as $node) {
    $outHtml .= $node->C14N();
}

// $outHtml now contains the "fixed" HTML as a string

See it working

【讨论】:

  • 太棒了,非常感谢您提供如此详尽的回答!我们肯定会这样做。比快速而肮脏的正则表达式解决方案要好得多。
【解决方案2】:

嗯,实际上不是一个解决方案,但主要是一个提示......

你可以开始玩ExceptionController

在那里,仅举例,您可以寻找 404 错误并检查附加到请求的查询字符串:

$request = $this->container->get('request');
....

if (404 === $exception->getStatusCode()) {
    $query = $request->server->get('QUERY_STRING');
    //...handle your logic
}

另一种解决方案是为此目的使用其控制器定义特殊路由,该路由将捕获对index.php 的请求并进行重定向等。只需在路由的requirements 中定义index.php 并将此路由移动到路由的顶部即可。

不是一个最明确的答案,但至少我希望我给了你一个方向......

干杯 ;)

【讨论】:

    【解决方案3】:

    您可以通过将http:\\ 放在链接前面来覆盖base 标记。也就是说,给出一个完整的 url,而不是一个相对的 URL。

    【讨论】:

    • 是的...虽然不是一个好的解决方案,是吗?这意味着新站点必须对所有内容使用绝对路径,从长远来看,这可能会适得其反……
    • 不一定...我有一个类似的问题,我只是以编程方式检查链接,如果它还没有以http://https:// 开头,我将它添加到开头字符串。添加链接之前只有几行代码。请注意,您可以使用 jQuery 或 PHH 执行此操作,但我使用 PHP。
    猜你喜欢
    • 2021-05-15
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多