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
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
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
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
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
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
qandcategory. - 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
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.