Супервалидация пользовательских данных
версия для печатиЗадача: обработать данные с формы обратной связи. А там полей штук 30(!), это форма запроса кредита. Решение в лоб - разбирать массив и валидировать каждое значение, - это жесть. Выход в использовании возможностей php-функций filter_*_array(). Там много заморочек, я более-менее разобрался с этим семейством. Пищу здесь, чтоб в следующий раз не шариться в исходниках.
Пример не относится к банковской системе, он интереснее :)
if (!empty($_POST)) {
$filters = array(
'id' => array('filter' => FILTER_VALIDATE_INT,
'options' => array('min_range' => 0,),
),
'name' => array('filter' => FILTER_SANITIZE_STRING,
'flags' => FILTER_FLAG_NO_ENCODE_QUOTES,
),
'orient' => array('filter' => FILTER_CALLBACK,
'options' => array('PDFPattern', 'filterOrientation')
),
'content' => FILTER_UNSAFE_RAW, //без доп.флагов можно просто 'null' указать.
'alias' => null, //без проверки
//... и остальные n-цать полей ...
);
$post = array_intersect_key($_POST, $filters); //оставляем только ожидаемые элементы
$post = filter_var_array($post, $filters); //дезинфекция
$post = array_map('addslashes', $post); //экранируем кавычки для записи в БД
extract($post);
if (!isset($id)) { die ('Error: wrong id'); }
//... Отдельные шаманства над $content и $alias ...
//... запись в БД ...
}
Если не нужно разбирать в переменные, тогда проще:
// $post = array_intersect_key($_POST, $filters);
$_POST = filter_input_array(INPUT_POST, $filters); //дезинфекция
$_POST = array_map('addslashes', $_POST); //экранируем кавычки для записи в БД
// extract($post);
Обратите внимание, что filter_input_array(INPUT_POST, ...) работает с исходным массивом $_POST, т.е. любые его изменения в скрипте будут проигнорированы. В то же время, filter_var_array() принимает любой массив. Я вообще не понимаю, зачем нужна первая функция :)
Для MySQL предпочительнее использовать mysqli_real_escape_string() вместо addslashes(). Если вы еще пользуете расширение php_MySQL (без i), то рекомендую озадачиться рефакторингом, ибо оно устарело начиная с версии PHP 5.5.0, и будет удалено в дальнейшем.
Флаги FILTER_REQUIRE_ARRAY и FILTER_FORCE_ARRAY полезны, когда POST-параметр передан, как массив, например:
<select name="items[]" multiple>
<option> ...
<option> ...
</select>
Флаги объединяются вертикальной чертой
$filters = array(
'items' => array('filter' => FILTER_VALIDATE_INT,
'flags' => FILTER_REQUIRE_ARRAY | FILTER_FORCE_ARRAY,
'options' => array('min_range' => 1, 'max_range' => 7),
),
...
);
При этом валидатор возращает значение в массиве:
'items' => array (size=3) 0 => int 3 1 => false //"левое" значение. Не прошло валидацию. 2 => int 6span> r
Замечание: при ипользовании флага FILTER_FORCE_ARRAY любые данные будут возращены как массив, не зависимо от типа входящих данных.
Фильтры FILTER_VALIDATE_INT и FILTER_SANITIZE_NUMBER_INT выполняют разные задачи. Валидатор проверяет значение и приводит его к числовому типу либо возращает возращает логическое false. Дезинфекция только убирает из значения нечисловые символы, при этом никак не преобразует тип данных. Т.е. если число передано в строке (например через $_POST), то в строке оно и останется.
Валидация параметра 'orient' из примера выше использует классовую callback-функцию. Использование callback-функций дает большие возможности. Например, можно создать функцию, проверяющую данные регулярным выражением. В настройке фильтров валидации вызывать эту функцию и передавать параметром нужную регулярку.
[1oo%, EoF]Понравилась статья? Расскажите о ней друзьям: