Lesson 94 of 100
HTTP concepts15 min5 checksPHP 8.5

Build and Parse Query Strings

Turn PHP arrays into URL-encoded query strings with http_build_query and read them back with parse_str, using fixed in-memory strings only.

01 · THE IDEAREAD → TRY → LEARN

What a query string is

The part of a URL after ? is a query string: a list of name=value pairs joined by &. Characters such as spaces, ampersands and slashes would break that format, so they are encoded. PHP gives you two complementary tools. http_build_query() turns an array into a query string, and parse_str() turns a query string back into an array. This lesson uses fixed strings only, so nothing here touches the network.

Building a query string

The signature is http_build_query(array|object $data, string $numeric_prefix = "", ?string $arg_separator = null, int $encoding_type = PHP_QUERY_RFC1738): string. For most work you only pass the data. Note three behaviours in the first example:

  • null values are left out entirely.
  • true becomes 1 and false becomes 0.
  • With the default encoding, a space becomes +.
Example
<?php
$data = ['name' => 'Ada Lovelace', 'city' => 'London', 'skip' => null, 'ok' => true, 'no' => false];
echo http_build_query($data), "\n";
echo http_build_query($data, '', '&', PHP_QUERY_RFC3986), "\n";
Output
name=Ada+Lovelace&city=London&ok=1&no=0
name=Ada%20Lovelace&city=London&ok=1&no=0

The fourth argument chooses the encoding. PHP_QUERY_RFC1738 is the form style with + for spaces. PHP_QUERY_RFC3986 uses %20, which is often what you want when composing a URL. The third argument sets the separator. Passing null falls back to the arg_separator.output setting, so pass '&' explicitly if you need a predictable result.

Parsing a query string

parse_str(string $string, array &$result): void returns nothing. It fills the variable you pass by reference. Since PHP 8 the second argument is required. Every scalar value arrives as a string, even when it looks like a number. Bracket syntax creates nested arrays, and + and %XX sequences are decoded.

Example
<?php
parse_str('a=1&b[]=x&b[]=y&c[k]=v&d=hello+world%21', $out);
echo json_encode($out, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"a":"1","b":["x","y"],"c":{"k":"v"},"d":"hello world!"}

Because everything comes back as strings, a value that started as the integer 2 returns as "2". If your code cares about types, cast after parsing.

Round trips and nested data

Nested arrays are written with encoded brackets: tags[0]=php becomes tags%5B0%5D=php. Parsing reverses this, so structure survives the trip while scalar types do not.

Example
<?php
$filters = ['tags' => ['php', 'web'], 'page' => 2, 'q' => 'a&b'];
$query = http_build_query($filters);
echo $query, "\n";
parse_str($query, $back);
echo json_encode($back, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
tags%5B0%5D=php&tags%5B1%5D=web&page=2&q=a%26b
{"tags":["php","web"],"page":"2","q":"a&b"}

Notice that the literal & inside the value a&b was encoded as %26. That is why you should never build query strings by concatenating raw values yourself.

Edge cases and mistakes

  • Forgetting that parse_str() writes into its second argument. Its return value is void.
  • Expecting integers back from parse_str(). You always get strings for scalar values.
  • Relying on the default separator. Pass '&' for stable output.
  • Duplicate names. In a=1&a=2 the last one wins, unless you use bracket syntax such as a[].
  • Passing an object. Only its public properties are included, and __toString() is not called unless you cast the object yourself.
  • Key order. Output follows the array order, so sort with ksort() when you need a canonical form, for example for comparing or caching.

Worked plan for the exercise

You will write set_query_param(string $query, string $name, string $value): string. It parses the incoming query, sets or replaces one parameter, sorts the keys, and rebuilds the string using %20 for spaces. Work in this order:

  1. Call parse_str($query, $params) to get an array.
  2. Assign $params[$name] = $value, which replaces an existing entry or appends a new one.
  3. Call ksort($params) so the key order is canonical.
  4. Return http_build_query($params, '', '&', PHP_QUERY_RFC3986).

The tests check returned strings, covering an empty query, a replaced key, encoded characters and a nested array that must survive the trip.

Recap

Use http_build_query() to encode arrays safely, choose the RFC 3986 flag for %20 spaces, and pass an explicit '&' separator. Use parse_str() with an output variable to decode, remembering that scalars come back as strings. Sort keys when you need a stable, comparable result.

Before you start

Functions · Arrays · Types

You’ll practice
  • Use http_build_query and parse_str on fixed strings without HTTP I/O
  • Implement and test a deterministic PHP 8.4 function
Your task

Make set_query_param() 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.