Lesson 27 of 100
Validation12 min5 checksPHP 8.5

Input Validation: Check Before Using a Value

Learn to validate emails and integers with filter_var(), and to tell a rejected value apart from a valid zero by comparing strictly.

01 · THE IDEAREAD → TRY → LEARN

Why validate at all?

Data that arrives from a form, a query string or a file is just text. A user can type abc where you expect a number, or leave a field empty. If you use the value without checking it, the bug appears later, far from its cause. Validation is the habit of checking a value at the boundary of your code and either accepting it in a known shape or rejecting it.

Meet filter_var()

PHP's filter_var() takes a value, a filter and optional options. For validation you pick one of the FILTER_VALIDATE_* constants, such as FILTER_VALIDATE_EMAIL or FILTER_VALIDATE_INT. On success it returns the value in its filtered form. On failure it returns false, unless you pass the FILTER_NULL_ON_FAILURE flag, in which case it returns null.

Scalar values are converted to strings internally before filtering, so 42 and '42' are treated alike.

Here is an email check. The first value passes and comes back unchanged. The second fails and gives false.

Example
<?php
$values = ['bob@example.com', 'invalidemail'];
foreach ($values as $value) {
    echo json_encode(filter_var($value, FILTER_VALIDATE_EMAIL)), "\n";
}
Output
"bob@example.com"
false

Notice that a valid email returns the string itself, not true. The return value is the cleaned data, and false is the only signal of failure for this filter.

The valid-zero trap

Now consider FILTER_VALIDATE_INT. The string '0' is a perfectly good integer, and the filter returns the integer 0. But 0 is falsy in PHP, so a check like if ($result) or the shorthand $result ?: null treats a valid zero as a failure. This is a very common bug in quantity, page and offset fields, where zero is a legitimate answer.

The fix is a strict comparison with false:

Example
<?php
$result = filter_var('0', FILTER_VALIDATE_INT);
echo json_encode($result), "\n";
echo $result === false ? "rejected" : "valid", "\n";
$bad = filter_var('zero', FILTER_VALIDATE_INT);
echo $bad === false ? "rejected" : "valid", "\n";
Output
0
valid
rejected

The === operator compares type as well as value, so 0 === false is false while false === false is true. Use it whenever a filter's success value could itself be falsy.

Adding limits with options

Many filters accept options. For integers, min_range and max_range go inside an inner options array, and flags go in a flags field. Combining a range with FILTER_NULL_ON_FAILURE gives you a tidy result: an int or null, never false. That matches a ?int return type nicely.

Example
<?php
function parse_age(string $input): ?int {
    return filter_var($input, FILTER_VALIDATE_INT, [
        'options' => ['min_range' => 0, 'max_range' => 120],
        'flags' => FILTER_NULL_ON_FAILURE,
    ]);
}

echo json_encode(array_map('parse_age', ['0', '121', 'x'])), "\n";
Output
[0,null,null]

The zero survives, the out-of-range value is rejected, and the non-number is rejected. The caller now only has to test === null.

Validation versus sanitization

Validation answers "is this acceptable as it is?". Sanitization (FILTER_SANITIZE_*) changes a value to strip unwanted characters. For most input checks, prefer validating and rejecting. Silently rewriting what a user typed can hide mistakes.

Worked reasoning for the exercise

You will write parse_quantity(string $input): ?int. It should accept whole numbers from 0 to 100 inclusive and return them as integers. Anything else returns null.

  1. Call filter_var() with FILTER_VALIDATE_INT and a range of 0 to 100.
  2. Capture the result in a variable.
  3. Compare strictly against false. If it is false, return null. Otherwise return the integer.

The boundary cases matter: '0' and '100' must be accepted, '101' must be rejected, and '12.5' is not a whole number so it must be rejected too. Casting with (int) would turn '12.5' into 12 and 'abc' into 0, which is exactly the silent acceptance validation is meant to prevent.

Recap

  • filter_var() with a FILTER_VALIDATE_* filter returns the filtered value or false.
  • FILTER_NULL_ON_FAILURE switches the failure value to null.
  • Use === to separate failure from a valid 0.
  • Prefer rejecting bad input over casting it into something that looks valid.
Before you start

Functions · Conditionals

You’ll practice
  • Validate an email or integer with filter_var
  • Distinguish rejected input from a valid zero
Your task

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