web php

Query Strings

A query string is the part of a URL after ?. It is commonly used for search terms, filters, sorting, pagination, tracking codes, and other values that describe which view of a resource the user wants.

Query strings are visible, bookmarkable, shareable, and controlled by the client. They are useful for read-only requests, but they are not a safe place for secrets or trusted decisions.

Reading query values

In a web request, PHP puts query string values in $_GET.

PHP example
<?php

declare(strict_types=1);

$query = [
    'q' => ' php forms ',
    'page' => '2',
];

$term = trim((string) ($query['q'] ?? ''));
$page = filter_var($query['page'] ?? 1, FILTER_VALIDATE_INT, [
    'options' => ['default' => 1, 'min_range' => 1],
]);

echo $term . ' page ' . $page . PHP_EOL;

// Prints:
// php forms page 2

This example uses $query so it runs from the command line. In an actual controller, that array might come from $_GET or a framework request object.

Building query strings

Use http_build_query() instead of manually joining strings. It handles URL encoding for you.

PHP example
<?php

declare(strict_types=1);

$params = [
    'q' => 'php forms',
    'page' => 2,
    'sort' => 'newest',
];

echo '/search?' . http_build_query($params) . PHP_EOL;

// Prints:
// /search?q=php+forms&page=2&sort=newest

Manual string building often breaks when values contain spaces, &, =, Unicode characters, or empty values.

Preserve filters when changing pages

Pagination links should preserve the current search and filter values.

PHP example
<?php

declare(strict_types=1);

function pageUrl(array $query, int $page): string
{
    $query['page'] = $page;

    return '/products?' . http_build_query($query);
}

echo pageUrl(['q' => 'boots', 'colour' => 'black'], 3) . PHP_EOL;

// Prints:
// /products?q=boots&colour=black&page=3

This is a common real-world task in product lists, admin tables, search results, and reports.

Repeated Values And Normalisation

A query key can contain more than one value. Filter forms often submit arrays such as category[]=books&category[]=courses.

PHP example
<?php

declare(strict_types=1);

$query = ['category' => [' books ', 'courses', '']];
$categories = array_values(array_filter(
    array_map('trim', $query['category'] ?? []),
    static fn (string $category): bool => $category !== ''
));

echo implode(', ', $categories) . PHP_EOL;

// Prints:
// books, courses

Validate both the outer shape and each value. A client can submit category=books instead of an array, or submit unexpected values that should not reach a database query unchanged.

When filters map to known choices, use an allow-list. When a search term is free text, trim it and enforce a sensible length limit.

Query Strings And Database Queries

Query values often become search or sort options, so they cross a security boundary. Do not place a submitted sort column directly into SQL. Map accepted public values to known internal choices:

PHP example
<?php

declare(strict_types=1);

$requestedSort = 'price';
$sortColumns = [
    'newest' => 'created_at',
    'price' => 'price_pennies',
];

$sortColumn = $sortColumns[$requestedSort] ?? $sortColumns['newest'];

echo $sortColumn . PHP_EOL;

// Prints:
// price_pennies

Prepared statements protect data values. An allow-list protects structural choices such as column names and sort directions.

Common mistakes

  • Using query strings for passwords, tokens, or private data.
  • Treating query values as trusted because they came from your own links.
  • Manually concatenating query strings without URL encoding.
  • Forgetting to preserve existing filters when adding pagination or sorting.
  • Using query strings for state-changing actions such as delete or checkout.

Use query strings for describing a view. Use POST plus CSRF protection for browser actions that change server state.

What you should be able to do

After this lesson, you should be able to read query string values, validate scalar and repeated filters, build URLs with http_build_query(), preserve filters across links, map sort options safely, and explain why query strings are not a place for secrets or state-changing actions.

Practice

Task: Build Filtered Page Links

Create a PHP helper for search result pagination links.

Requirements

  • Accept an array of current query values.
  • Accept a target page number.
  • Validate the page number so it is at least 1.
  • Preserve existing filters such as q and category.
  • Build the URL with http_build_query().
  • Show one normal case and one invalid page case.
  • Add a short note explaining why query strings are good for filters but not for secrets.

Check your work

The output should show URLs that can be bookmarked or shared without losing the current filters.

Show solution
PHP example
<?php

declare(strict_types=1);

function resultsPageUrl(array $query, int $page): string
{
    $query['page'] = max(1, $page);

    return '/search?' . http_build_query($query);
}

echo resultsPageUrl(['q' => 'php forms', 'category' => 'web'], 2) . PHP_EOL;
echo resultsPageUrl(['q' => 'php forms', 'category' => 'web'], -5) . PHP_EOL;

// Prints:
// /search?q=php+forms&category=web&page=2
// /search?q=php+forms&category=web&page=1

Query strings are good for filters because they make the current view shareable and bookmarkable. They are not good for secrets because URLs are visible in browser history, server logs, analytics tools, proxy logs, and screenshots.