Lesson 39 of 100
Strings15 min5 checksPHP 8.5

Encode URL Components with rawurlencode

Learn how rawurlencode protects path segments under RFC 3986, how it differs from form-style urlencode, and build a safe path helper.

01 · THE IDEAREAD → TRY → LEARN

Why URLs need encoding

A URL gives certain characters special jobs. A / separates path segments, ? starts a query string, & separates parameters, and % introduces an escape. If user data contains one of these characters and you paste it into a URL unchanged, the data can change the structure of the URL. A department named sales and marketing/Miami should be one path segment, but a raw slash makes it look like two.

Percent-encoding fixes this. Each unsafe byte is replaced by % followed by two hexadecimal digits. A space becomes %20, a slash becomes %2F, and a literal percent sign becomes %25.

rawurlencode

rawurlencode(string $string): string encodes a string according to RFC 3986. Every character except ASCII letters, digits and the four characters -, _, . and ~ is replaced by a percent escape. Strings are processed as bytes, so a multibyte UTF-8 character becomes several escapes: é is %C3%A9.

The function always returns a string and has no failure mode. An empty string comes back as an empty string.

Example
<?php
echo rawurlencode('sales and marketing/Miami'), "\n";
Output
sales%20and%20marketing%2FMiami

The slash is encoded, which is exactly what you want when the whole value is one segment.

rawurlencode versus urlencode

urlencode() produces the older form-style encoding used by application/x-www-form-urlencoded. Two differences matter here: it turns a space into +, and it also encodes ~. In a path, a + is an ordinary character, not a space, so form encoding can corrupt path segments.

Example
<?php
$value = 'a b+c~';
echo json_encode([
    'raw' => rawurlencode($value),
    'form' => urlencode($value),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"raw":"a%20b%2Bc~","form":"a+b%2Bc%7E"}

Decoding mirrors this. rawurldecode() leaves + alone, while urldecode() converts + to a space. Decode with the partner of the function you used to encode.

Encode the parts, not the whole URL

The most common mistake is encoding a complete URL. Running rawurlencode on https://example.com/a would encode the colon and the slashes and break it. Instead, encode each component separately and then join the pieces with the delimiters you control.

For a path, that means encoding every segment and joining with /:

Example
<?php
function pathFromSegments(array $segments): string {
    return implode('/', array_map('rawurlencode', $segments));
}

echo pathFromSegments(['files', 'Q1 report', '2024/25']), "\n";
Output
files/Q1%20report/2024%2F25

The / inside 2024/25 is data, so it is escaped. The slashes between segments are structure, so they stay.

Edge cases

  • An empty segment stays empty, so joining can produce //. Decide whether your application allows that.
  • Encoding twice turns %20 into %2520. Encode raw data exactly once, at the moment you build the URL.
  • Unreserved characters -_.~ pass through unchanged, so there is no need to escape them yourself.
  • Rawurlencode does not know about character sets. It encodes whatever bytes it receives, so make sure your strings are UTF-8 first.

Exercise contract

Write buildUrlPath(array $segments): string. It must encode every segment with rawurlencode, join the segments with /, and put a single / at the start. An empty array returns just /. The checks cover spaces, an embedded slash, an empty list, unreserved characters, a literal percent sign and a UTF-8 character. Two tempting shortcuts fail: using urlencode turns spaces into +, and encoding the already joined string also encodes the separators.

Recap

Use rawurlencode for URL path components, because it follows RFC 3986 and writes spaces as %20. Use urlencode only for form-style data. Always encode individual components, never a finished URL, and encode each value only once.

Before you start

Functions · Arrays · Types

You’ll practice
  • Encode path components with rawurlencode and distinguish form encoding
  • Implement and test a deterministic PHP 8.4 function
Your task

Make buildUrlPath() pass all 5 checks. Run your code as often as you like, then check your answer.

exercise.phpSaved in this browserPHP 8.5
CONSOLE & CHECKS● Ready

Ready when you are

Your output will appear here.
Make it work. Then make it pass.

PHP loads on your first run. Each check starts fresh. Your code stays in this browser; clearing site data removes your progress. A check or the task looks wrong? Report a problem with this exercise.