如何在PHP中正确创建HTML链接?

时间:2019-03-26 21:08:10

标签: php url

这个问题与rawurlencodehttp_build_queryhtmlspecialchars的正确使用有关。

直到现在,我在普通PHP中创建HTML链接的标准方法是:

$qs = [
    'foo' => 'foo~bar',
    'bar' => 'bar foo',
];
echo '<a href="?' . http_build_query($qs) . '">Link</a>';

最近我了解到这不是100%正确的。这里有几个问题:

  • http_build_query默认使用 PHP_QUERY_RFC1738 而不是 PHP_QUERY_RFC3986 。 RFC3986是被取代的标准RFC1738,在PHP中仅保留用于传统用途。
  • 虽然键和值部分中的“特殊” HTML字符将被编码为百分比编码的表示形式,但参数分隔符将为“&”号。在大多数理智的情况下,这不是问题,但是有时您的密钥名称可能是quot;,然后您的链接将变得无效:

    $qs = [
        'a' => 'a',
        'quot;' => 'bar',
    ];
    echo '<a href="?' . http_build_query($qs) . '">Link</a>';
    

    上面的代码将生成此链接:?a=a"%3B=bar
    IMO表示,在HTML中,需要使用第三参数http_build_query调用函数&amp;,并在&中仅使用header('Location: ...');调用上下文感知。另一种选择是将其通过htmlspecialchars传递,然后以HTML显示。

  • urlencode的PHP手册( IMO早已不推荐使用)建议仅对查询字符串的值部分进行编码,然后将整个查询字符串通过{ {1}},然后以HTML显示。在我看来,这是非常不正确的。关键部分仍可能包含禁止的URL字符。

    htmlentities

我的结论是按照以下方式做些事情:

$query_string = 'foo=' . urlencode($foo) . '&bar=' . urlencode($bar);
echo '<a href="mycgi?' . htmlentities($query_string) . '">';

在PHP中创建HTML链接的推荐方法是什么?有没有比我想出的更简单的方法?我错过了任何要点吗?

1 个答案:

答案 0 :(得分:0)

由于过去4个月中没有人能够提供答案,因此以下是我的发现。

如何动态创建带有查询字符串的HTML链接?

如果您需要创建要在HTML链接中使用的查询字符串(例如<a href="index.php?param1='.$value.'">Link</a>),则应使用http_build_query。 该函数接受4个参数,第一个是查询数据的数组/对象。在大多数情况下,其他三个参数无关。

$qs = [
    'a' => 'a',
    'quot;' => 'bar foo',
];
echo '<a href="?' . http_build_query($qs) . '">Link</a>';

但是,您仍然应该通过htmlspecialchars 传递函数的输出,以正确编码&“一个好的框架会自动执行此操作,例如Laravel的{{}}”

echo '<a href="?' . htmlspecialchars(http_build_query($qs)) . '">Link</a>';

或者,您可以将第三个参数作为http_build_query传递给'&amp;',而将第二个参数null传递给&amp;。这将使用&来代替htmlspecialchars。{p>

关于空格
为了在表单数据(即查询字符串)中使用,空格should be encoded as + and in any other place it should be encoded as %20例如new%20page.php?my+field=my+val。这是为了确保与所有浏览器的向后可比性。您可以使用更新的RFC3986,它将把空格编码为%20,并且可以在所有常见的浏览器中使用,并且可以与现代标准保持一致。

echo '<a href="?' . http_build_query($qs, null, '&amp;', PHP_QUERY_RFC3986) . '">Link</a>';

rawurlencodeurlencode

对于?之前的URL的任何部分,都应使用rawurlencode。例如:

$subdir = rawurlencode('blue+light blue');
echo '<a href="'.$subdir.'/index.php">rawurlencode</a>';

如果在上例中使用urlencode,则链接将断开。 urlencode的用途非常有限,应避免使用。

请勿通过rawurlencode传递整个URL。如果分隔符/和URL中的其他特殊字符要实现其功能,则不应进行编码。


脚注

关于使用http_build_query的最佳实践没有普遍的共识,只是它应该像HTML上下文中的任何其他输出一样通过htmlspecialchars传递。

Laravel使用http_build_query($array, null, '&', PHP_QUERY_RFC3986)

CodeIgniter使用http_build_query($query)

Symfony使用http_build_query($extra, '', '&', PHP_QUERY_RFC3986)

Slim使用http_build_query($queryParams)

CakePHP使用http_build_query($query)

Twig使用http_build_query($url, '', '&', PHP_QUERY_RFC3986)