Core PHP 8 programs with output 15 Q/A 5 MCQs

Learning Objectives – after this chapter you will be able to:

  • Explain why all external data must be filtered.
  • Use filter_var(), filter_var_array(), filter_input(), filter_input_array() and filter_has_var().
  • Tell validating filters from sanitizing filters and use options and flags.
  • Filter several inputs at once and write a filter callback.
  • Know which filters were deprecated or removed in PHP 8.
What is a PHP Filter?

PHP filters are used to validate and filter data coming from insecure sources, such as user input. Testing, validating and filtering user input or custom data is an important part of every web application, and the PHP filter extension is designed to make data filtering easier and quicker.

Why use a filter?

Almost all web applications depend on external input – usually from a user or from another application (such as a web service). By using filters you can be sure your application gets the correct input type. You should always filter all external data! Input filtering is one of the most important application security issues.

What is external data?

  • Input data from a form
  • Cookies
  • Web services data
  • Server variables
  • Database query results
Filter Functions
FunctionPurpose
filter_var()Filters a single variable with a specified filter.
filter_var_array()Filters several variables with the same or different filters.
filter_input()Gets one input variable (GET, POST, COOKIE, SERVER, ENV) and filters it.
filter_input_array()Gets several input variables and filters them with the same or different filters.
filter_has_var()Checks whether an input variable of a given type exists.
filter_list()Returns a list of all supported filter names.

The input types for filter_input() are the constants INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER and INPUT_ENV.

Validating and Sanitizing

There are two kinds of filters:

Validating filters

  • are used to validate user input;
  • have strict format rules (like URL or e-mail validation);
  • return the expected type on success, or false on failure.

Sanitizing filters

  • are used to allow or disallow specified characters in a string;
  • have no data-format rules;
  • always return the (cleaned) string.
Validate filters
FilterPurpose
FILTER_VALIDATE_INTValidate value as integer, optionally within a range.
FILTER_VALIDATE_FLOATValidate value as float.
FILTER_VALIDATE_BOOLEAN (FILTER_VALIDATE_BOOL)TRUE for "1", "true", "on", "yes"; FALSE for "0", "false", "off", "no", ""; NULL otherwise (with FILTER_NULL_ON_FAILURE).
FILTER_VALIDATE_EMAILValidate value as e-mail address.
FILTER_VALIDATE_URLValidate value as URL, optionally with required components.
FILTER_VALIDATE_IPValidate value as IP address, optionally only IPv4 or IPv6, or not from private or reserved ranges.
FILTER_VALIDATE_REGEXPValidate value against a Perl-compatible regular expression.
FILTER_VALIDATE_DOMAINValidate a domain name.
FILTER_VALIDATE_MACValidate a MAC address.
Sanitize filters
FilterPurpose
FILTER_SANITIZE_EMAILRemove all characters except letters, digits and !#$%&'*+-=?^_{|}~@.[] (and the backtick).
FILTER_SANITIZE_URLRemove all characters except letters, digits and $-_.+!*'(),{}|\^~[]<>#%";/?:@&= (and the backtick).
FILTER_SANITIZE_NUMBER_INTRemove all characters except digits and + -.
FILTER_SANITIZE_NUMBER_FLOATRemove all characters except digits, + - and optionally . , e E.
FILTER_SANITIZE_SPECIAL_CHARSHTML-escape '"<>& and characters with ASCII value less than 32.
FILTER_SANITIZE_FULL_SPECIAL_CHARSSame as htmlspecialchars() with ENT_QUOTES.
FILTER_SANITIZE_ENCODEDURL-encode the string.
FILTER_SANITIZE_ADD_SLASHESApply addslashes() (PHP 7.3+).
FILTER_UNSAFE_RAWDo nothing, optionally strip or encode special characters.
FILTER_CALLBACKCall a user-defined function to filter data.

PHP 8 changes. FILTER_SANITIZE_MAGIC_QUOTES was removed in PHP 8.0 (use FILTER_SANITIZE_ADD_SLASHES). FILTER_SANITIZE_STRING and its alias FILTER_SANITIZE_STRIPPED are deprecated since PHP 8.1 – use htmlspecialchars() or FILTER_SANITIZE_FULL_SPECIAL_CHARS instead.

Validating an Integer – filter_var()

In the example below we validate an integer:

File: htdocs/phpbook/ch21/int.php
<?php
$int = 123;
if (filter_var($int, FILTER_VALIDATE_INT) === false) {
    echo("Integer is not valid");
} else {
    echo("Integer is valid");
}
?>
OUTPUT browser · http://localhost/phpbook/ch21/int.php
Integer is valid

The code uses the FILTER_VALIDATE_INT filter. Since 123 is a valid integer, the output is "Integer is valid". If we try a variable that is not an integer (like "123abc"), the output is "Integer is not valid":

File: htdocs/phpbook/ch21/int2.php
<?php
foreach ([123, "123abc", "45", 0, "7.5"] as $value) {
    $r = filter_var($value, FILTER_VALIDATE_INT);
    echo var_export($value, true) . " → " . ($r === false ? "not valid" : "valid, int $r") . "<br>";
}
?>
OUTPUT browser · http://localhost/phpbook/ch21/int2.php
123 → valid, int 123
'123abc' → not valid
'45' → valid, int 45
0 → valid, int 0
'7.5' → not valid

Compare the result with === false. A plain if (!filter_var(...)) wrongly rejects the valid value 0, because 0 is falsy.

Options and Flags

Options and flags add extra filtering behaviour to a filter. Different filters have different options and flags. Below we validate an integer with the min_range and max_range options:

File: htdocs/phpbook/ch21/range.php
<?php
$var = 300;
$int_options = array(
    "options" => array(
        "min_range" => 0,
        "max_range" => 256
    )
);
if (filter_var($var, FILTER_VALIDATE_INT, $int_options) === false) {
    echo("Integer is not valid");
} else {
    echo("Integer is valid");
}
?>
OUTPUT browser · http://localhost/phpbook/ch21/range.php
Integer is not valid

Options must be put in an associative array named "options". A flag can be given directly, or in the "flags" element. Since 300 is not in the range 0–256, the output is "Integer is not valid".

File: htdocs/phpbook/ch21/flags.php
<?php
echo "<pre>";
var_dump(filter_var("192.168.1.10", FILTER_VALIDATE_IP));
var_dump(filter_var("192.168.1.10", FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE));
var_dump(filter_var("yes", FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var("maybe", FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
var_dump(filter_var("https://www.php.net/manual", FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED));
var_dump(filter_var("1,250.75 rupees", FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
var_dump(filter_var("<b>Hi</b> & bye", FILTER_SANITIZE_FULL_SPECIAL_CHARS));
echo "</pre>";
?>
OUTPUT browser · http://localhost/phpbook/ch21/flags.php
string(12) "192.168.1.10"
bool(false)
bool(true)
NULL
string(26) "https://www.php.net/manual"
string(7) "1250.75"
string(31) "<b>Hi</b> & bye"

The last line returns &lt;b&gt;Hi&lt;/b&gt; &amp; bye (31 characters); the browser displays these entities as the original characters, which is exactly why the text is now safe to print.

Validating Input – filter_input()

Let us validate input from a form. First confirm that the input data exists, then filter it with filter_input(). In the example below the input variable "email" is sent to the PHP page with GET:

File: htdocs/phpbook/ch21/validate_input.php
<?php
if (!filter_has_var(INPUT_GET, "email")) {
    echo("Input type does not exist");
} else {
    if (!filter_input(INPUT_GET, "email", FILTER_VALIDATE_EMAIL)) {
        echo "E-Mail is not valid";
    } else {
        echo "E-Mail is valid";
    }
}
?>
OUTPUT browser · http://localhost/phpbook/ch21/validate_input.php?email=asha@example
E-Mail is not valid
OUTPUT browser · validate_input.php?email=asha@example.com
E-Mail is valid

Example explained: the script checks whether an "email" input variable of the GET type exists; if it does, it checks whether it is a valid e-mail address.

Sanitizing Input

Let us clean up a URL sent from a form. First we confirm that the input exists, then we sanitize it with filter_input(). The input variable "url" is sent with POST:

File: htdocs/phpbook/ch21/sanitize.php
<?php
if (!filter_has_var(INPUT_POST, "url")) {
    echo("Input type does not exist");
} else {
    $url = filter_input(INPUT_POST, "url", FILTER_SANITIZE_URL);
    echo "Received : " . htmlspecialchars($_POST["url"]) . "<br>";
    echo "Sanitized: " . htmlspecialchars($url);
}
?>
OUTPUT browser · POST http://localhost/phpbook/ch21/sanitize.php (url=http://www.exämple.com/my page?q=php)
Received : http://www.exämple.com/my page?q=php
Sanitized: http://www.exmple.com/mypage?q=php

The script checks whether the "url" POST input exists; if it does, it removes the invalid characters (here the space and the "ä") and stores the result in $url.

Filtering Multiple Inputs

A form almost always has more than one field. To avoid calling filter_var() or filter_input() again and again, use filter_var_array() or filter_input_array(). In this example filter_input_array() filters three GET variables – a name, an age and an e-mail address:

File: htdocs/phpbook/ch21/multi.php
<?php
$filters = array(
    "name" => array(
        "filter" => FILTER_SANITIZE_FULL_SPECIAL_CHARS
    ),
    "age" => array(
        "filter"  => FILTER_VALIDATE_INT,
        "options" => array(
            "min_range" => 1,
            "max_range" => 120
        )
    ),
    "email" => FILTER_VALIDATE_EMAIL,
);
$result = filter_input_array(INPUT_GET, $filters);
if (!$result["age"]) {
    echo("Age must be a number between 1 and 120.<br>");
} elseif (!$result["email"]) {
    echo("E-Mail is not valid.<br>");
} else {
    echo("User input is valid<br>");
}
echo "<pre>";
var_dump($result);
echo "</pre>";
?>
OUTPUT browser · http://localhost/phpbook/ch21/multi.php?name=Asha%20%3Cb%3ESharma%3C/b%3E&age=21&email=asha@example.com
User input is valid

array(3) {
  ["name"]=>
  string(30) "Asha <b>Sharma</b>"
  ["age"]=>
  int(21)
  ["email"]=>
  string(16) "asha@example.com"
}

Example explained:

  1. An array is set containing the names of the input variables and the filters used on them.
  2. filter_input_array() is called with the GET input variables and that array.
  3. The "age" and "email" elements of $result are checked for invalid input. (If an input is invalid, it is false after filter_input_array().)

The second parameter of filter_input_array() can be an array or a single filter ID. If it is a single filter ID, all values in the input array are filtered with that filter. If it is an array, it must follow these rules:

  • It must be an associative array with the input variable names as keys (like "age").
  • Each value must be a filter ID, or an array specifying the filter, flags and options.
Using a Filter Callback

With FILTER_CALLBACK you can call a user-defined function and use it as a filter, giving you full control of the data filtering. You can write your own function or use an existing PHP function. The function is specified like an option – in an associative array named "options". In the example below a user-created function converts all "_" to spaces:

File: htdocs/phpbook/ch21/callback.php
<?php
function convertSpace($string)
{
    return str_replace("_", " ", $string);
}
$string = "Bhopal_City_of_Lakes!";
echo filter_var($string, FILTER_CALLBACK, array("options" => "convertSpace"));
echo "<br>";
echo filter_var("  php filters  ", FILTER_CALLBACK, array("options" => "trim"));
?>
OUTPUT browser · http://localhost/phpbook/ch21/callback.php
Bhopal City of Lakes!
php filters
Key Takeaways
  • Always filter external data: forms, cookies, web services, server variables, database results.
  • filter_var() filters one value; filter_input() reads and filters one input; the _array versions do many at once; filter_has_var() checks existence.
  • Validating filters return the value or false; sanitizing filters always return a cleaned string.
  • Options go in an "options" array; flags change filter behaviour.
  • Compare validation results with === false so that 0 is accepted.
  • FILTER_SANITIZE_STRING is deprecated (8.1) and FILTER_SANITIZE_MAGIC_QUOTES removed (8.0).
Program File

Extract the ZIP into C:\xampp\htdocs. It creates the folder phpbook/ch21 used in the file labels above; open the programs at http://localhost/phpbook/… with Apache (and MySQL, where needed) started in the XAMPP Control Panel.

Question / Answer (15 questions)

Answer : A function of the filter extension used to validate (check) or sanitize (clean) data from insecure sources such as forms, cookies and web services.

Answer : Because it can be wrong or malicious; filtering ensures the application receives data of the correct type and format, which is one of the most important security measures.

Answer : Form input, cookies, web services data, server variables and database query results.

Answer : filter_var() filters any variable or value you pass; filter_input() reads a variable directly from an input source (INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV) and filters it.

Answer : It checks whether a variable of the specified input type exists, e.g. filter_has_var(INPUT_GET, "email").

Answer : Validating filters check data against strict format rules and return the value (converted to the right type) or false; sanitizing filters remove or encode unwanted characters and always return a string.

Answer : Additional settings for a filter. Options, given in an array named "options", set values like min_range and max_range; flags, such as FILTER_FLAG_NO_PRIV_RANGE, modify the filter's behaviour.

Answer : filter_var($age, FILTER_VALIDATE_INT, ["options" => ["min_range" => 1, "max_range" => 120]]) and compare the result with false.

Answer : Because the valid value 0 is falsy, so if (!filter_var(…)) would wrongly treat 0 as invalid.

Answer : It removes all characters that are not allowed in a URL, such as spaces and non-ASCII letters.

Answer : It gets several input variables of one type and filters each with its own filter, flags and options in a single call, returning an array of results.

Answer : It must be associative with input names as keys, and each value must be a filter ID or an array giving "filter", "flags" and "options".

Answer : A filter that calls a user-defined or built-in function, named in the "options" element, to filter the value – giving full control over the filtering.

Answer : FILTER_SANITIZE_MAGIC_QUOTES was removed in 8.0 (use FILTER_SANITIZE_ADD_SLASHES), and FILTER_SANITIZE_STRING/FILTER_SANITIZE_STRIPPED were deprecated in 8.1 (use htmlspecialchars() or FILTER_SANITIZE_FULL_SPECIAL_CHARS).

Answer : filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE).
MCQ Test : Check Your Understanding (5 questions)

Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.

Q1. A validating filter returns what when the data is invalid?

Show Answer

Correct Answer : B. false
Validation filters return false on failure.

Q2. Which constant reads a variable from the query string in filter_input()?

Show Answer

Correct Answer : B. INPUT_GET
INPUT_GET refers to $_GET data.

Q3. Range limits for FILTER_VALIDATE_INT are given in an array named:

Show Answer

Correct Answer : C. "options"
Options such as min_range and max_range go in "options".

Q4. Which filter calls a user-defined function?

Show Answer

Correct Answer : A. FILTER_CALLBACK
FILTER_CALLBACK with "options" => "functionName".

Q5. Which filter is deprecated in PHP 8.1?

Show Answer

Correct Answer : C. FILTER_SANITIZE_STRING
Use htmlspecialchars() or FILTER_SANITIZE_FULL_SPECIAL_CHARS instead.

Bibliography/References

The notes on this page are the author’s own compilation from the e-book PHP: Basics to Advance. Every program was run on Apache with PHP 8 and MariaDB, and the output shown is the real result of that run. The works listed below were consulted and are cited for attribution and further reading. Product names and trademarks belong to their respective owners.

  1. The PHP Group. (n.d.). PHP Manual – Data Filtering. https://www.php.net/manual/en/book.filter.php
  2. The PHP Group. (n.d.). PHP Manual – Validate filters. https://www.php.net/manual/en/filter.filters.validate.php
  3. The PHP Group. (n.d.). PHP Manual – Sanitize filters. https://www.php.net/manual/en/filter.filters.sanitize.php
  4. The PHP Group. (n.d.). PHP Manual – filter_input_array. https://www.php.net/manual/en/function.filter-input-array.php
  5. The PHP Group. (n.d.). PHP Manual – Deprecated features in PHP 8.1. https://www.php.net/manual/en/migration81.deprecated.php