'settype() vs filter_var()

Which if the folowing lines is better to use for making sure my code is more secure. Should I be using the settype function of the filter_var functions?

settype($number,'integer') 

or

filter_var($number, FILTER_SANITIZE_NUMBER_INT);

Thanking You



Solution 1:[1]

As the documentation says about FILTER_SANITIZE_NUMBER_INT:

Remove all characters except digits, plus and minus sign.

So if you are expecting for instance, an ID to be used in a SQL query, I would go with a regular expression to check that I only have digits /^[0-9]+$/. Because FILTER_SANITIZE_NUMBER_INT would allow -12 which would not make sense in this context.

The main difference between filter_var and settype is that one will parse the variable as a string, and return a string, and the other will cast it to an integer.

$string = "+12";
var_dump(filter_var($string, FILTER_SANITIZE_NUMBER_INT));
settype($string, "integer");
var_dump($string);

Output:

string(3) "+12"
int(12)

So it really depends on the context.

Solution 2:[2]

The question title is not specific on this and I am not sure if the intention was not to use \FILTER_VALIDATE_INT instead of \FILTER_SANITIZE_NUMBER_INT. So I am writing my approach here down, for people which are googling such.

In my opinion, to validate and convert, \filter_var is much closer to what "is expected" - it is not benevolent and does not bottom out to 0...

<?php

$types = [
    "suffix" => "10x",
    "prefix nonsenes" => "a10",
    "prefix too many zeroes" => "00010",
    "prefix octal" => "010",
    "prefix hex" => "0x10",
    "valid" => "10",
    "valid plus" => "+10",
    "valid minus" => "-10",
];

foreach ($types as $name => $string) {
    echo "$string ($name)". PHP_EOL;
    
    try {
        $asFilter = \filter_var($string, \FILTER_VALIDATE_INT);
        $asSet = $string; $settypeSuccess = \settype($asSet, "integer");
        
        echo "\tfilter_var: "; var_dump($asFilter);
        echo "\tsettype ". ($$settypeSuccess ? "successful": "FAILED") .": "; var_dump($asSet);
        
    } catch (\Throwable $t) {
        echo $t->getMessage();
    }
    
    echo PHP_EOL;
}

outputs

10x (suffix)
        filter_var: bool(false)
        settype successful: int(10)

a10 (prefix nonsenes)
        filter_var: bool(false)
        settype successful: int(0)

00010 (prefix too many zeroes)
        filter_var: bool(false)
        settype successful: int(10)

010 (prefix octal)
        filter_var: bool(false)
        settype successful: int(10)

0x10 (prefix hex)
        filter_var: bool(false)
        settype successful: int(0)

10 (valid)
        filter_var: int(10)
        settype successful: int(10)

+10 (valid plus)
        filter_var: int(10)
        settype successful: int(10)

-10 (valid minus)
        filter_var: int(-10)
        settype successful: int(-10)

For \filter_var there are also flags available: \FILTER_FLAG_ALLOW_OCTAL, \FILTER_FLAG_ALLOW_HEX, \FILTER_NULL_ON_FAILURE.

NB: Documentation for \filter_var states: "Note that scalar values are converted to string internally before they are filtered." Which can lead to unexpected behavior as reported by https://3v4l.org/CZW0W

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2