How to properly URL encode a string in PHP?

PhpUrlencode

Php Problem Overview


I'm making a search page, where you type a search query and the form is submitted to search.php?query=your query. What PHP function is the best and that I should use for encoding/decoding the search query?

Php Solutions


Solution 1 - Php

For the URI query use urlencode/urldecode; for anything else use rawurlencode/rawurldecode.

The difference between urlencode and rawurlencode is that

Solution 2 - Php

The cunningly-named http://uk.php.net/manual/en/function.urlencode.php">urlencode()</a> and http://uk.php.net/manual/en/function.urldecode.php">urldecode()</a>;.

However, you shouldn't need to use urldecode() on variables that appear in $_POST and $_GET.

Solution 3 - Php

Here is my use case, which requires an exceptional amount of encoding. Maybe you think it contrived, but we run this on production. Coincidently, this covers every type of encoding, so I'm posting as a tutorial.

Use case description

Somebody just bought a prepaid gift card ("token") on our website. Tokens have corresponding URLs to redeem them. This customer wants to email the URL to someone else. Our web page includes a mailto link that lets them do that.

PHP code

// 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().

Test case

  1. Run the code on a PHP test site (is there a canonical one I should mention here?)
  2. Click the link
  3. Send the email
  4. Get the email
  5. Click that link

You should see:

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

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

Solution 4 - Php

You can use URL Encoding Functions PHP has the

rawurlencode() 

function

ASP has the

Server.URLEncode() 

function

In JavaScript you can use the

encodeURIComponent() 

function.

Solution 5 - Php

Based on what type of RFC standard encoding you want to perform or if you need to customize your encoding you might want to create your own class.

/**
 * 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;
        }
    }
}

Use example:

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

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

Will output:

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 protected])"

* Find out more about RFC standards: https://datatracker.ietf.org/doc/rfc3986/ and https://stackoverflow.com/questions/996139/urlencode-vs-rawurlencode

Solution 6 - Php

You know how people keep saying things like: "Never manually craft a json string in PHP -- always call json_encode() for stability/reliability."?

Well, if you are building a query string, then I say: "Never manually craft a url query string in PHP -- always call http_build_query() for stability/reliability."

Demo:

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

echo http_build_query($array);

echo "\n---\n";

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

Output:

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.

Here is an educational answer on Joomla Stack Exchange which encourages the use of &amp; as the custom delimiter: Why are Joomla url query strings commonly delimited with "&" instead of "&"?

Initially packaging your query string data in array form offers a compact and readable structure, then the call of http_build_query() does the hard work and can prevent data corruption. I generally opt for this technique even for small query string construction.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAliView Question on Stackoverflow
Solution 1 - PhpGumboView Answer on Stackoverflow
Solution 2 - PhpOliver CharlesworthView Answer on Stackoverflow
Solution 3 - PhpWilliam EntrikenView Answer on Stackoverflow
Solution 4 - PhpAmranur RahmanView Answer on Stackoverflow
Solution 5 - PhpDevWLView Answer on Stackoverflow
Solution 6 - PhpmickmackusaView Answer on Stackoverflow