使用 DOMDocument() ,我替换了$message中的链接并添加了一些内容,例如[@MERGEID]。当我使用 $dom_document->saveHTML() 保存更改时,链接将被“某种” URL编码。 [@MERGEID]变为%5B@MERGEID%5D

稍后在我的代码中,我需要用ID替换[@MERGEID]。因此,我搜索了urlencode('[@MERGEID]')-但是, urlencode() 将符号(@)上的商业广告更改为%40,而saveHTML()则保持不变。因此没有匹配项-'%5B@MERGEID%5D' != '%5B%40MERGEID%5D'
现在,我知道可以运行str_replace('%40', '@', urlencode('[@MERGEID]'))来获取在$ message中定位合并变量所需的内容。

我的问题是,DOMDocument使用什么RFC规范,为什么它与urlencode甚至rawurlencode不同?我有什么办法可以保存str_replace吗?

演示代码:

$message = '<a href="http://www.google.com?ref=abc" data-tag="thebottomlink">Google</a>';
$dom_document = new \DOMDocument();
libxml_use_internal_errors(true); //Supress content errors
$dom_document->loadHTML(mb_convert_encoding($message, 'HTML-ENTITIES', 'UTF-8'));
$elements = $dom_document->getElementsByTagName('a');
foreach($elements as $element) {
    $link = $element->getAttribute('href'); //http://www.google.com?ref=abc
    $tag = $element->getAttribute('data-tag'); //thebottomlink
    if ($link) {
        $newlink = 'http://www.example.com/click/[@MERGEID]?url=' . $link;
        if ($tag) {
            $newlink .= '&tag=' . $tag;
        }
        $element->setAttribute('href', $newlink);
    }
}
$message = $dom_document->saveHTML();
$urlencodedmerge = urlencode('[@MERGEID]');
die($message . ' and url encoded version: ' . $urlencodedmerge);
//<a data-tag="thebottomlink" href="http://www.example.com/click/%5B@MERGEID%5D?url=http://www.google.com?ref=abc&amp;tag=thebottomlink">Google</a> and url encoded version: %5B%40MERGEID%5D

最佳答案

我相信这两种编码有不同的用途。 urlencode()编码"a string to be used in a query part of a URL",而$element->setAttribute('href', $newlink);编码完整的URL以用作URL。

例如:

urlencode('http://www.google.com'); // -> http%3A%2F%2Fwww.google.com

这对于编码查询部分很方便,但是不能在<a href='...'>上使用。

然而:
$element->setAttribute('href', $newlink); // -> http://www.google.com

会正确编码字符串,以便仍可在href中使用。之所以无法编码@的原因是因为它无法分辨@是查询的一部分还是userinfoemail url的一部分(例如mailto:[email protected][email protected])

解决方案
  • 您可以使用[@MERGEID]来代替@@MERGEID@@。然后,稍后将其替换为您的ID。该解决方案甚至不需要使用urlencode
  • 如果您坚持使用urlencode,则可以只使用%40而不是@。因此,您的代码将像这样$newlink = 'http://www.example.com/click/[%40MERGEID]?url=' . $link;
  • 您还可以执行类似$newlink = 'http://www.example.com/click/' . urlencode('[@MERGEID]') . '?url=' . $link;
  • 的操作

    09-10 11:42