PHP / Basic: values and request foundations / Lesson 5
HTTP input, forms, and validation boundaries
Interpret request data without assuming superglobals are trusted records. Separate method checks, input shape, domain validation, and error feedback using synthetic submissions.
On this page
Lesson goals
- Distinguish transport shape from domain values.
- Validate scalar input without loose false checks.
- Design safe rejection and correction behavior.
A request is external evidence, not a trusted object
A server adapter reads a request method, path, headers, cookies, and body according to its execution interface. PHP populates superglobals for supported input formats, but values still originate outside the trust boundary. Form controls commonly produce strings and can produce arrays through naming conventions; JSON bodies follow a different decoding path. Do not assume $_POST represents every possible request body or that a hidden input is authoritative. Convert the external representation into a small validated record before calling domain functions, keeping the raw source available only as needed for safe correction or diagnosis.
Validate syntax and range explicitly
The quantity rule here accepts a string that the integer validator recognizes within one through twenty. The parser rejects arrays before filtering and returns null for invalid input, preserving a distinct domain result. filter_var returns false on validation failure for this filter, so strict comparison matters when zero is a valid value in another contract. Do not silently trim or normalize identifiers if the product requires exact bytes. Numeric parsing policies, leading zeros, signs, and localization should be agreed and tested rather than inferred from a function name. A cast alone is not a substitute.
<?php
declare(strict_types=1);
function quantity(mixed $raw): ?int {
if (!is_string($raw)) { return null; }
$value = filter_var($raw, FILTER_VALIDATE_INT, ["options" => ["min_range" => 1, "max_range" => 20]]);
return $value === false ? null : $value;
}
echo quantity("3"), PHP_EOL;
echo quantity("3x") === null ? "invalid
" : "valid
";
echo quantity(["3"]) === null ? "invalid shape
" : "valid
";
3
invalid
invalid shape
The parser rejects both malformed text and an array without treating either as a plausible quantity.
Method and validation decisions precede effects
Choose allowed methods and content types before creating a reservation. A page read should not create an enrollment merely because a query parameter asks it to. A state-changing form needs server-side permission checks and a CSRF strategy appropriate to its session design, not just client JavaScript validation. Return a defined rejection for wrong shape or invalid values and preserve legitimate entered fields for correction. The local decision model below produces status-like outcomes without opening a server or changing state; real HTTP emission is a separate adapter responsibility. Keep that evidence distinction visible.
<?php
declare(strict_types=1);
function decide(string $method, array $input): array {
if ($method !== "POST") { return ["status" => 405]; }
if (!isset($input["name"]) || !is_string($input["name"]) || trim($input["name"]) === "") {
return ["status" => 422, "error" => "name required"];
}
return ["status" => 200, "name" => trim($input["name"])];
}
echo json_encode(decide("GET", []), JSON_THROW_ON_ERROR), PHP_EOL;
echo json_encode(decide("POST", ["name" => " Ada "]), JSON_THROW_ON_ERROR), PHP_EOL;
{"status":405}
{"status":200,"name":"Ada"}
These integers model outcomes, not emitted HTTP responses. No enrollment or session is created.
Validation should enable correction
Associate each error with its field and explain the expected format in safe text. Preserve valid inputs unless retaining them would expose sensitive data, and escape them when rendering the correction form. Validation messages must not contain raw SQL, file paths, or session identifiers. Distinguish missing input, invalid type, invalid format, and rejected domain state when those distinctions help the user or caller. Do not let an unrelated invalid field prevent every test from reaching the quantity rule. Test focused failures with otherwise valid data so each rejection demonstrates the intended validator.
Bound input size and uploaded-file behavior
A valid field value can still arrive inside an oversized request or an unexpected multipart shape. Request limits, upload error codes, file size, media inspection, and storage naming are separate concerns from text validation. Never trust a client filename as a destination path or execute uploaded content. Keep a bounded server-side policy and store outside executable paths where appropriate. This course’s examples use no uploaded files or real requests; use an isolated fixture when studying those APIs. Record limitations so a passing scalar parser is not reported as complete form or upload security.
Common errors and fixes
A form field arrives as an array unexpectedly
- Why it happens
- The caller assumes every external value is a scalar string.
- How to fix it
- Validate shape before string or numeric operations.
- Prevent it next time
- Include array-shaped input in boundary tests.
A GET request changes enrollment state
- Why it happens
- Read navigation and write effects are mixed.
- How to fix it
- Define allowed methods and guard state-changing handlers.
- Prevent it next time
- Review method, permission, and CSRF checks together.
Rejected input loses every valid field
- Why it happens
- Error handling ignores the correction task.
- How to fix it
- Preserve safe valid data and attach clear field errors.
- Prevent it next time
- Test correction and successful resubmission as one flow.
Check your understanding
1. A zero count is permitted and filter_var returns zero. Should if (!$value) reject it?
Show worked solution
No. Compare $value === false for this validation filter, then apply the allowed range separately. A truthiness check would conflate a valid zero with failure. Test zero, malformed text, and missing input as different cases rather than using one generic invalid test.
2. A hidden price field says 1 cent. What should the server trust?
Show worked solution
Use the validated course identifier to obtain the authoritative server-side price and permission context. The hidden field can be presentation data or a consistency hint, but is editable client input. Reject inconsistent or unauthorized actions before writing a reservation or payment effect.
Key takeaways
- Validate external shape before converting values.
- Method, permission, CSRF, and correction are separate parts of a form contract.