如何在 PHP 中正确地对字符串进行 URL 编码?

我正在做一个搜索页面,在那里你输入一个搜索查询,表格提交到 search.php?query=your query。什么 PHP 函数是最好的,我应该用来编码/解码搜索查询?

272317 次浏览

巧妙地命名为 Urlencode ()Urldecode ()

但是,对于出现在 $_POST$_GET中的变量,应该不需要使用 urldecode()

对于 URI 查询,使用 urlencode/urldecode; 对于其他任何查询,使用 rawurlencode/rawurldecode

urlencoderawurlencode的区别在于

下面是我的用例,它需要异常大量的编码。也许你认为这是人为的,但我们在生产中运行这个。巧合的是,这涵盖了所有类型的编码,所以我把它作为一个教程发布。

用例描述

有人刚刚在我们的网站上买了一张预付礼品卡(“令牌”)。令牌有相应的 URL 来赎回它们。此客户希望将 URL 电子邮件发送给其他人。我们的网页包括一个 mailto链接,让他们这样做。

PHP 代码

// The order system generates some opaque token
$token = 'w%a&!e#"^2(^@azW';


// Here is a URL to redeem that token
$redeemUrl = 'https://httpbin.org/get?token=' . urlencode($token);


// Actual contents we want for the email
$subject = 'I just bought this for you';
$body = 'Please enter your shipping details here: ' . $redeemUrl;


// A URI for the email as prescribed
$mailToUri = 'mailto:?subject=' . rawurlencode($subject) . '&body=' . rawurlencode($body);


// Print an HTML element with that mailto link
echo '<a href="' . htmlspecialchars($mailToUri) . '">Email your friend</a>';

Note: the above assumes you are outputting to a text/html document. If your output media type is text/json then simply use $retval['url'] = $mailToUri; because output encoding is handled by json_encode().

测试案例

  1. 在 PHP 测试站点(有没有一个我应该在这里提到的规范?)上运行代码
  2. 点击链接
  3. 发邮件
  4. 收邮件
  5. 点击那个链接

你应该看看:

"args": {
"token": "w%a&!e#\"^2(^@azW"
},

And of course this is the JSON representation of $token above.

可以使用 URL 编码函数

rawurlencode()

功能。

NET 具有

Server.URLEncode()

功能。

在 JavaScript 中,可以使用

encodeURIComponent()

功能。

根据要执行的 RFC 标准编码的类型,或者如果需要自定义编码,则可能需要创建自己的类。

/**
* UrlEncoder make it easy to encode your URL
*/
class UrlEncoder{
public const STANDARD_RFC1738 = 1;
public const STANDARD_RFC3986 = 2;
public const STANDARD_CUSTOM_RFC3986_ISH = 3;
// add more here


static function encode($string, $rfc){
switch ($rfc) {
case self::STANDARD_RFC1738:
return  urlencode($string);
break;
case self::STANDARD_RFC3986:
return rawurlencode($string);
break;
case self::STANDARD_CUSTOM_RFC3986_ISH:
// Add your custom encoding
$entities = ['%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D', '%2B', '%24', '%2C', '%2F', '%3F', '%25', '%23', '%5B', '%5D'];
$replacements = ['!', '*', "'", "(", ")", ";", ":", "@", "&", "=", "+", "$", ",", "/", "?", "%", "#", "[", "]"];
return str_replace($entities, $replacements, urlencode($string));
break;
default:
throw new Exception("Invalid RFC encoder - See class const for reference");
break;
}
}
}

举例说明:

$dataString = "https://www.google.pl/search?q=PHP is **great**!&id=123&css=#kolo&email=me@liszka.com)";


$dataStringUrlEncodedRFC1738 = UrlEncoder::encode($dataString, UrlEncoder::STANDARD_RFC1738);
$dataStringUrlEncodedRFC3986 = UrlEncoder::encode($dataString, UrlEncoder::STANDARD_RFC3986);
$dataStringUrlEncodedCutom = UrlEncoder::encode($dataString, UrlEncoder::STANDARD_CUSTOM_RFC3986_ISH);

将输出:

string(126) "https%3A%2F%2Fwww.google.pl%2Fsearch%3Fq%3DPHP+is+%2A%2Agreat%2A%2A%21%26id%3D123%26css%3D%23kolo%26email%3Dme%40liszka.com%29"
string(130) "https%3A%2F%2Fwww.google.pl%2Fsearch%3Fq%3DPHP%20is%20%2A%2Agreat%2A%2A%21%26id%3D123%26css%3D%23kolo%26email%3Dme%40liszka.com%29"
string(86)  "https://www.google.pl/search?q=PHP+is+**great**!&id=123&css=#kolo&email=me@liszka.com)"

* 了解更多有关 RFC 标准的资料: Https://datatracker.ietf.org/doc/rfc3986/ 以及 urlencode vs rawurlencode?

你知道人们一直在说: “永远不要在 PHP 中手动构建 JSON 字符串——总是为了稳定性/可靠性而调用 json_encode()。”?

如果您正在构建查询字符串,那么我会说: “永远不要用 PHP 手动构建 URL 查询字符串ーー为了稳定性/可靠性,请始终调用 http_build_query()。”

演示 :

$array = [
'query' => 'your query',
'example' => null,
'Qbert says:' => '&%=#?/'
];


echo http_build_query($array);


echo "\n---\n";


echo http_build_query($array, '', '&amp;');

产出:

query=your+query&Qbert+says%3A=%26%25%3D%23%3F%2F
---
query=your+query&amp;Qbert+says%3A=%26%25%3D%23%3F%2F

The fine print on this function is that if an element in the input array has a null value, then that element will not be included in the output string.

下面是一个关于 Joomla Stack Exchange 站点的教育性答案,它鼓励使用 &amp;作为自定义分隔符: 为什么 Joomla URL 查询字符串通常用“ &”而不是“ &”分隔?

最初以数组形式打包查询字符串数据提供了一个紧凑和可读的结构,然后 http_build_query()的调用完成了这项艰巨的工作,并且可以防止数据损坏 。即使对于小型查询字符串构造,我通常也选择这种技术。