Обработка и проверка данных формы в PHP

В целом, вариантов обработки и проверки данных формы существует достаточно много. Я же предпочитаю использовать свою, выработанную на практике, последовательность действий, которая позволяет минимизировать усилия и добиться максимального результата. Об этом и поговорим.

Шаг 1: инициализация переменных. Т.к. я использую шаблонизатор (тот же Smarty), то, для упрощения задачи, работаю сразу с переменной $_POST, которую экранирую в шаблоне. Но для её использования она должна существовать. Поэтому в программной части произвожу инициализацию нужных мне переменных, например:

if ( !isset($_POST['name']) ) $_POST['name'] = '';

Шаг 2: событие отправки данных из формы. Обычно форма и обработчик данных у меня находятся в одном скрипте, т.к. это позволяет обрабатывать и сохранять в форме уже введённые данные наиболее простым способом. Дело за малым, т.е распознать событие отправки данных. Для этого, я указываю в кнопке атрибут name, например:

<input type="submit" name="send" value="Отправить...">

Очевидно, что переменная  $_POST['send'] на 1м шаге не инициализируется, её наличие служит маркером события, например:

if ( isset($_POST['name']) ) {
  /* код обработки данных из формы */
}

Шаг 3: фильтрация данных формы. Фильтрация данных у меня происходит в момент их обработки, для вывода вполне достаточно и экранирования. При этом, в процессе фильтрации, я создаю отдельные переменные, т.к. с ними проще работать, например:

$name = f($_POST['name'], 'string,nohtml,nonl,nows,trim');

Как вы видите, здесь я использую самописную php-функцию f(). Конечно, в PHP есть и filter_var(), но мне удобней использовать то, что я понимаю, и в том виде, который мне удобен.

Шаг 4: обработка данных фрпсы. Дальше идёт обработка созданных переменных на соответствие нужным требованиям и сбор ошибок в специальную переменную $errors_data, которая представляет собой обычный массив, инициализируемый на 1м шаге, например:

$errors_data = array();

Сама обработка ошибок может быть разной, в зависимости от требований, например:

if ( empty($name) ) $errors_data[] = 'Вы не указали Название.';
elseif ( strlen($name) > 60 ) $errors_data[] = ' Длинна Название не может быть больше 60 символов.';

Шаг 5: добавление данных из формы в БД. Добавлять данные можно куда угодно, но принцип остаётся тот же. Я проверяю наличие ошибок, и если они отсутствуют, выполняю добавление, например:

if ( sizeof($errors_data) <= 0 ) {
  /* код добавления данных */
}

Интересным моментом здесь является составление запроса на вставку данных формы в БД. Для этого я использую SET и массив его элементов с нужным экранированием, что позволяет добиться максимальной динамичности, например:

$set = array();
$set[] = "name = '". $db->escape($name) ."'";
if ( !empty($skype) ) $set[] = "skype = '". $db->escape($skype) ."'";

Другими словами, добавляются только те данные, которые нужны. Сам запрос при этом может иметь следующий вид:

$db->exec("INSERT INTO `nodes` SET ". implode(", ", $set));

Отмечу, что для работы с БД я использую самописный php-класс.

Ещё один момент. Для экономии ресурсов и снижения количества 404-ошибок (для удалённых данных), я не удаляю данные, а просто меняю их статус в БД. Таким образом, есть возможность заметить их новыми. Для этого проводится несложная проверка, например:

$id = $db->get_field("SELECT id FROM `nodes` WHERE status = '2' LIMIT 1");
if ( $count === false ) {
  $db->exec("INSERT INTO `nodes` SET ". implode(", ", $set));
} else {
  $db->exec("UPDATE `nodes` SET ". implde(", ", $set) . " WHERE id = '". $id ."' LIMIT 1");
}

Очевидно, что при таком варианте, следует учесть замену ряда значений на значения по умолчанию, например:

$set[] = "skype = '". ( empty($skype) ? $db->escape($skype) : "") ."'";

или даже так:

$set[] = "skype = '". $db->escape($skype) ."'";

Шаг 6: вывод ошибок обработки формы. В том случае, если при обработке данных на 4м шаге имеются ошибки, т.е. добавление данных в БД не произошло, мы должны вывести сообщение об ошибке. Для этого у нас есть массив $errors_data. Т.к. я использую шаблоничатор Smarty, то для этого у меня имеется отдельный шаблон errors.tpl, код которого имеет вид:

{if ( isset($errors_data) ) && ( is_array($errors_data) ) && ( sizeof($errors_data) > 0 )}
  <div class="errors">
    <p>Ошибка(-и):</p>
    <ul>{foreach $errors_data as $error}<li>{$error}</li>{/foreach}</ul>
  </div>
{/if}

Думаю, объяснять его не имеет смысла, но если коротко: есть ошибки – выводим их.

Шаг 7: экранирование переменных в шаблоне формы. Я уже говорил, что в форме я использую данные из переменной $_POST. Экранировать их в шаблонах достаточно просто, например:

<tr>
  <td><label for="name" class="request">Название:</label></td>
  <td><div class="df"><input type="text" id="name" name="name" value="{$smarty.post.name|escape}" maxlength="90"></div></td>
</tr>

Другими словами, по сути, здесь вполне достаточно и php-функции htmlspecialchars(). В некоторых случаях можно обойтись и без экранирования, за счёт проверки значения, например, в тех же SELECT тегах.

На этом у меня всё. Спасибо за внимание. Удачи!