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

Posted

技术标签:

【中文标题】如何正确地在 PHP 中对字符串进行 URL 编码?【英文标题】:How to properly URL encode a string in PHP? 【发布时间】:2011-06-12 07:22:17 【问题描述】:

我正在创建一个搜索页面,您可以在其中键入搜索查询并将表单提交给search.php?query=your query。什么 PHP 函数是最好的,我应该使用它来编码/解码搜索查询?

【问题讨论】:

您有遇到什么问题吗?浏览器和 PHP 应该已经自动处理了这个问题(例如,将 foo bar 放在文本字段中,在 URL 中创建 foo+bar)。 @Felix 我将使用file_get_contents调用搜索器脚本 【参考方案1】:

根据您要执行的 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?

【讨论】:

【参考方案2】:

这是我的用例,它需要大量的编码。也许你认为它做作,但我们在生产中运行它。巧合的是,这涵盖了所有类型的编码,因此我将其作为教程发布。

用例说明

有人刚刚在我们的网站上购买了预付礼品卡(“代币”)。令牌有相应的 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>';

注意:以上假设您正在输出到text/html 文档。如果您的输出媒体类型是text/json,那么只需使用$retval['url'] = $mailToUri;,因为输出编码由json_encode() 处理。

测试用例

    在 PHP 测试站点上运行代码(我应该在这里提到一个规范的代码吗?) 点击链接 发送电子邮件 获取电子邮件 点击该链接

你应该看到:

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

当然这是上面$token的JSON表示。

【讨论】:

等价,语义上更少(因为mailto:不是HTTP),你可以使用$mailToUri 'mailto:?' . http_build_query(['subject'=&gt;$subject, 'body'=&gt;$body], null, '&amp;', PHP_QUERY_RFC3986);【参考方案3】:

你可以使用 PHP 的 URL 编码函数

rawurlencode() 

功能

ASP 有

Server.URLEncode() 

功能

javascript 中你可以使用

encodeURIComponent() 

功能。

【讨论】:

【参考方案4】:

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

urlencoderawurlencode的区别在于

urlencode根据application/x-www-form-urlencoded编码(空格用+编码)而 rawurlencode 按照普通的Percent-Encoding 编码(空格用%20 编码)。

【讨论】:

application/x-www-form-urlencoded 只是 Percent-Encoding 的一种特殊变体,仅适用于编码 HTML 表单数据. @Click Upvote:它们无法以这种方式进行比较。 application/x-www-form-urlencoded 格式 Percent-Encoding 格式,除了空格用+ 编码而不是%20。除此之外,application/x-www-form-urlencoded 用于对表单数据进行编码,而 Percent-Encoding 具有更一般的用法。 rawurlencode() 兼容 javascript decodeURI() 函数 这条规则总是经验主义的吗?我的意思是,当我需要对查询字符串进行编码时,我总是使用urldecode。那么,URI 路径(例如/a/path with spaces/)和 URI 片段(例如#fragment)呢?我应该总是为这两个使用rawurldecode吗? 一个好的经验法则是路径(如 /my%20folder/)使用 rawurlencode;但是对于 POST 和 GET 字段,请使用 urlencode(例如 /?folder=my+folder)`【参考方案5】:

狡猾地命名为urlencode() 和urldecode()。

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

【讨论】:

能否请您详细说明为什么 urldecode() 不应与 $_POST 一起使用。因为我多年来一直这样做,没有任何问题。 我是否需要对通过 AJAX 发送到 PHP 文件的基本参数(例如 "name=b&amp;age=c&amp;location=d")进行编码?

以上是关于如何正确地在 PHP 中对字符串进行 URL 编码?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 WinForms 中对 URL 进行编码?

如何在 Excel VBA 中对字符串进行 URL 编码?

在 bash 脚本中对字符串进行 URL 编码

为 AJAX 请求在 jQuery 中对字符串进行 URL 编码

如何根据 RFC 2231 在 PHP 中对文件名进行编码?

如何在 PHP 中对谷歌地理编码 api 进行批量纬度/经度查找?