@hooligan377

Фильтрация, вопрос на засыпку?

Как будет правильно и безопасно фильтровать цифры?

Так:
$id = abs(intval($_GET['id']));

или так

$id = filter_var(trim($_GET['id']), FILTER_SANITIZE_NUMBER_INT);
  • Вопрос задан
  • 77 просмотров
Пригласить эксперта
Ответы на вопрос 3
SilenceOfWinter
@SilenceOfWinter Куратор тега PHP
та еще зажигалка...
это конечно не совсем "фильтрация", но и через is_numeric еще не один хакер не прорвался)
Ответ написан
Комментировать
sergiks
@sergiks Куратор тега PHP
♬♬
Разница двух вариантов касается ввода очень длинных значений и PHP_INT_MAX

Если введут, например, '1234567890123456789012345678901234567890',
то filter_var() вернет FALSE,
в то время, как у intval() получится 9223372036854775807.
Ответ написан
Комментировать
php666
@php666
PHP-макака
На самом деле, это очень нетривиальная задача, хотя кажется, что она простая. Когда я писал свой класс для БД mysql, мне необходимо было научиться понимать, где int, а где float. Как в их естественном типе, так и в типе строки.
Вот что вышло:

/**
 * Проверяет, является ли значение целым числом.
 *
 * @param mixed $input
 * @return boolean
 */
function isInteger($val)
{
    if (!is_scalar($val) || is_bool($val)) {
        return false;
    }

    return isFloat($val) ? false : preg_match('~^((?:\+|-)?[0-9]+)$~', $val) === 1;
}

/**
 * Проверяет, является ли значение числом с плавающей точкой.
 *
 * @param mixed $input
 * @return boolean
 */
function isFloat($val)
{
    if (!is_scalar($val) || is_bool($val)) {
        return false;
    }

    $type = gettype($val);

    if ($type === "double") {
        return true;
    } else {
        return preg_match("/^([+-]*\\d+)*\\.(\\d+)*$/", $val) === 1;
    }
}

foreach ([
             '11111111111111111', 11111111111111111, // > PHP_INT_MAX - presents in PHP as float
             1, '10', '+1', '1.1', 1.1, .2, 2., '.2', '2.',
             '-2.', '-.2', null, [], true, false, 'string'
         ] as $value) {
    echo $value . ':' . gettype($value) . ' is Integer? - '  . (isInteger($value) ? 'yes' : 'no') . PHP_EOL;
    echo $value . ':' . gettype($value) . ' is Float? - '  . (isFloat($value) ? 'yes' : 'no') . PHP_EOL;
}


11111111111111111:string is Integer? - yes
11111111111111111:string is Float? - no
11111111111111111:integer is Integer? - yes
11111111111111111:integer is Float? - no
1:integer is Integer? - yes
1:integer is Float? - no
10:string is Integer? - yes
10:string is Float? - no
+1:string is Integer? - yes
+1:string is Float? - no
1.1:string is Integer? - no
1.1:string is Float? - yes
1,1:double is Integer? - no
1,1:double is Float? - yes
0,2:double is Integer? - no
0,2:double is Float? - yes
2:double is Integer? - no
2:double is Float? - yes
.2:string is Integer? - no
.2:string is Float? - yes
2.:string is Integer? - no
2.:string is Float? - yes
-2.:string is Integer? - no
-2.:string is Float? - yes
-.2:string is Integer? - no
-.2:string is Float? - no // тут проблема
:NULL is Integer? - no
:NULL is Float? - no
Array:array is Integer? - no
Array:array is Float? - no
1:boolean is Integer? - no
1:boolean is Float? - no
:boolean is Integer? - no
:boolean is Float? - no
string:string is Integer? - no
string:string is Float? - no


И да. Считаю, что любая т.н. "санитарная обработка" - это зло (кроме банального trim). Надо делать именно проверку данных, а любая санитария меняет данные, что не есть правильно.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы