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()andfilter_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
| Function | Purpose |
|---|---|
| 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
| Filter | Purpose |
|---|---|
| FILTER_VALIDATE_INT | Validate value as integer, optionally within a range. |
| FILTER_VALIDATE_FLOAT | Validate 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_EMAIL | Validate value as e-mail address. |
| FILTER_VALIDATE_URL | Validate value as URL, optionally with required components. |
| FILTER_VALIDATE_IP | Validate value as IP address, optionally only IPv4 or IPv6, or not from private or reserved ranges. |
| FILTER_VALIDATE_REGEXP | Validate value against a Perl-compatible regular expression. |
| FILTER_VALIDATE_DOMAIN | Validate a domain name. |
| FILTER_VALIDATE_MAC | Validate a MAC address. |
Sanitize filters
| Filter | Purpose |
|---|---|
| FILTER_SANITIZE_EMAIL | Remove all characters except letters, digits and !#$%&'*+-=?^_{|}~@.[] (and the backtick). |
| FILTER_SANITIZE_URL | Remove all characters except letters, digits and $-_.+!*'(),{}|\^~[]<>#%";/?:@&= (and the backtick). |
| FILTER_SANITIZE_NUMBER_INT | Remove all characters except digits and + -. |
| FILTER_SANITIZE_NUMBER_FLOAT | Remove all characters except digits, + - and optionally . , e E. |
| FILTER_SANITIZE_SPECIAL_CHARS | HTML-escape '"<>& and characters with ASCII value less than 32. |
| FILTER_SANITIZE_FULL_SPECIAL_CHARS | Same as htmlspecialchars() with ENT_QUOTES. |
| FILTER_SANITIZE_ENCODED | URL-encode the string. |
| FILTER_SANITIZE_ADD_SLASHES | Apply addslashes() (PHP 7.3+). |
| FILTER_UNSAFE_RAW | Do nothing, optionally strip or encode special characters. |
| FILTER_CALLBACK | Call 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:
<?php
$int = 123;
if (filter_var($int, FILTER_VALIDATE_INT) === false) {
echo("Integer is not valid");
} else {
echo("Integer is valid");
}
?>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":
<?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>";
}
?>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:
<?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");
}
?>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".
<?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>";
?>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 <b>Hi</b> & 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:
<?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";
}
}
?>E-Mail is not valid
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:
<?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);
}
?>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:
<?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>";
?>User input is valid
array(3) {
["name"]=>
string(30) "Asha <b>Sharma</b>"
["age"]=>
int(21)
["email"]=>
string(16) "asha@example.com"
}Example explained:
- An array is set containing the names of the input variables and the filters used on them.
filter_input_array()is called with the GET input variables and that array.- The "age" and "email" elements of
$resultare checked for invalid input. (If an input is invalid, it isfalseafterfilter_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:
<?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"));
?>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_arrayversions 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
=== falseso that 0 is accepted. FILTER_SANITIZE_STRINGis deprecated (8.1) andFILTER_SANITIZE_MAGIC_QUOTESremoved (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)
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.
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.
- The PHP Group. (n.d.). PHP Manual – Data Filtering. https://www.php.net/manual/en/book.filter.php
- The PHP Group. (n.d.). PHP Manual – Validate filters. https://www.php.net/manual/en/filter.filters.validate.php
- The PHP Group. (n.d.). PHP Manual – Sanitize filters. https://www.php.net/manual/en/filter.filters.sanitize.php
- The PHP Group. (n.d.). PHP Manual – filter_input_array. https://www.php.net/manual/en/function.filter-input-array.php
- The PHP Group. (n.d.). PHP Manual – Deprecated features in PHP 8.1. https://www.php.net/manual/en/migration81.deprecated.php