filter_var($value, FILTER_VALIDATE_*, $options) returns the value converted to its type, or false. The third argument is a flags integer or an array with 'flags' and 'options' keys (min_range, max_range, regexp, default):
<?php
$rating = ['options' => ['min_range' => 1, 'max_range' => 5]];
echo json_encode([
filter_var(' 42 ', FILTER_VALIDATE_INT), // spaces are allowed
filter_var('4.2', FILTER_VALIDATE_INT),
filter_var('9', FILTER_VALIDATE_INT, $rating),
filter_var('maybe', FILTER_VALIDATE_BOOL, FILTER_NULL_ON_FAILURE),
filter_var('ann@example', FILTER_VALIDATE_EMAIL),
filter_var('javascript://x%0Aalert(1)', FILTER_VALIDATE_URL), // valid!
filter_var('10.0.0.5', FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE),
], JSON_UNESCAPED_SLASHES), "\n";
try {
filter_var('five', FILTER_VALIDATE_INT, FILTER_THROW_ON_FAILURE); // PHP 8.5
} catch (Filter\FilterFailedException $e) {
echo $e::class, ': ', $e->getMessage(), "\n";
}[42,false,false,null,false,"javascript://x%0Aalert(1)",false] Filter\FilterFailedException: filter validation failed: filter int not satisfied by 'five'
The result is a real int. FILTER_VALIDATE_BOOL (8.0's name for ..._BOOLEAN) with FILTER_NULL_ON_FAILURE gives true for "1", "true", "on" and "yes", false for "0", "false", "off", "no" and "", and null otherwise. The email filter checks RFC 822 syntax without dotless domains, not whether a mailbox exists; the URL filter accepts any scheme, so check it or use the URI extension (The URI Extension). FILTER_FLAG_GLOBAL_RANGE (8.2) rejects private and reserved IPs. filter_input(INPUT_GET, 'page', ...) reads the request as it arrived: on 8.5.4 it ignored a later $_GET['page'] = '99', applied 'default' => 1 to a missing key and to page=abc, and returned null under the CLI. filter_has_var() tells a missing key from an empty one.