如何在 PHP 中正确创建 HTML 链接? [英] How to properly create HTML links in PHP?

查看:32
本文介绍了如何在 PHP 中正确创建 HTML 链接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题是关于rawurlencode的正确使用,http_build_query &htmlspecialchars.

This question is about the proper use of rawurlencode, http_build_query & htmlspecialchars.

到目前为止,我在普通 PHP 中创建 HTML 链接的标准方法是:

Until now my standard way of creating HTML link in vanilla PHP was this:

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

最近我了解到这不是 100% 正确的.以下是几个问题:

Recently I have learned that this is not 100% correct. Here are few issues:

  • http_build_query 默认使用 PHP_QUERY_RFC1738 而不是 PHP_QUERY_RFC3986.RFC3986 是标准并取代了 RFC1738,它在 PHP 中仅保留用于遗留用途.
  • 虽然键和值部分中的特殊"HTML 字符将被编码为百分比编码表示,但参数分隔符将是一个&符号.在大多数正常情况下,这不会有问题,但有时您的键名可能是 quot;,然后您的链接将无效:

  • http_build_query uses by default PHP_QUERY_RFC1738 instead of PHP_QUERY_RFC3986. RFC3986 is the standard and superseded RFC1738 which in PHP is only kept for legacy use.
  • While the "special" HTML characters in the key and value part will be encoded to the percent-encoded representation, the argument separator will be an ampersand. In most sane situations this would not be a problem, but sometimes your key name might be quot; and then your link will become invalid:

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

上面的代码会生成这个链接:?a=a"%3B=bar!
IMO 这意味着函数 http_build_query 需要在 HTML 中使用第三个参数 & 调用上下文感知,并且仅使用 &header('Location: ...'); 中.另一种选择是在以 HTML 显示之前通过 htmlspecialchars 传递它.

The code above will generate this link: ?a=a"%3B=bar!
IMO this implies that the function http_build_query needs to be called context-aware with the 3-rd argument &amp; when in HTML, and with just & when in header('Location: ...');. Another option would be to pass it through htmlspecialchars before displaying in HTML.

urlencode<的 PHP 手册/a>(IMO 早就应该弃用了)建议只对查询字符串的值部分进行编码,然后通过 htmlentities 传递整个查询字符串,然后在 HTML 中显示.这对我来说看起来很不正确;关键部分仍可能包含禁止的 URL 字符.

PHP manual for urlencode (which should be deprecated long time ago IMO) suggests to encode only the value part of query string and then pass the whole query string through htmlentities before displaying in HTML. This looks very incorrect to me; the key part could still contain forbidden URL characters.

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

我的结论是沿着这条线做一些事情:

My conclusion is to do something along this lines:

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

在 PHP 中创建 HTML 链接的推荐方法是什么?有没有比我想出的更简单的方法?我是否遗漏了任何关键点?

What is the recommended way to create HTML links in PHP? Is there an easier way than what I came up with? Have I missed any crucial points?

推荐答案

如何使用查询字符串动态构建 HTML 链接?

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

How to dynamically build HTML links with query string?

If you need to create query string to be used in HTML link (e.g. <a href="index.php?param1='.$value.'">Link</a>) then you should use http_build_query. This function accepts 4 parameters, with the first one being an array/object of query data. For the most part the other 3 parameters are irrelevant.

$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>';

或者,您可以将第三个参数作为 '&amp;' 传递给 http_build_query,留下第二个 null.这将使用 &amp; 而不是 &,这是 htmlspecialchars 会做的.

Alternatively you can pass the third argument to http_build_query as '&amp;', leaving the second one null. This will use &amp; instead of & which is what htmlspecialchars would do.

关于空间.
对于在表单数据(即查询字符串)中使用,空格 应编码为 + 并在任何其他地方编码应该编码为 %20 例如new%20page.php?my+field=my+val.这是为了确保与所有浏览器的向后可比性.您可以使用较新的 RFC3986,它将空格编码为 %20,它可以在所有常见浏览器中工作,并符合现代标准.

About spaces.
For use in form data (i.e. query strings) the space should be encoded as + and in any other place it should be encoded as %20 e.g. new%20page.php?my+field=my+val. This is to ensure backwards comparability with all browsers. You can use the newer RFC3986 which will encode the spaces as %20 and it will work in all common browsers as well as be up to date with modern standards.

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


rawurlencode vs urlencode

对于 之前的 URL 的任何部分? 你应该使用 rawurlencode.例如:


rawurlencode vs urlencode

For any part of URL before ? you should use rawurlencode. For example:

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

如果在上面的例子中你使用了 urlencode,链接就会被破坏.urlencode 的用途非常有限,应避免使用.

If in the above example you used urlencode the link would be broken. urlencode has very limited use and should be avoided.

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

Do not pass whole URL through rawurlencode. Separators / and other special characters in URL should not be encoded if they are to fulfil their function.

脚注

对于使用 http_build_query 的最佳实践没有普遍的共识,除了应该像 HTML 上下文中的任何其他输出一样通过 htmlspecialchars 传递这一事实.

There is no general agreement on the best practices for using http_build_query, other than the fact it should be passed through htmlspecialchars just like any other output in HTML context.

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

Laravel uses http_build_query($array, null, '&', PHP_QUERY_RFC3986)

CodeIgniter 使用

CodeIgniter uses http_build_query($query)

a> 使用 http_build_query($extra, '', '&', PHP_QUERY_RFC3986)

Slim 使用 http_build$queryParams)

CakePHP 使用 http_build_query($query)

Twig> 使用

Twig uses http_build_query($url, '', '&', PHP_QUERY_RFC3986)

这篇关于如何在 PHP 中正确创建 HTML 链接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆