Работа с формами в XPDK производится в два этапа. Первый этап – подготовка формы: извлечение из БД списка полей, занесения в них имеющихся данных (или значений по умолчанию в случае отсутствия этих данных), а также формирование HTML-кода для отображения формы и JavaScript для предварительной проверки введенных пользователем данных.
Второй этап – получение данных из формы, выполнение их проверки с использованием динамически создаваемых PHP-функций и помещение в хеш-массив, ключи которого соответствуют полям формы. Для создания таких функций используется стандартная PHP-функция create_function, а их коды хранится вместе с описанием полей формы. Важно заметить, что для каждого из полей можно задать свою собственную функцию проверки, что существенно снижает вероятность возникновения ошибок при удалении существующих полей или добавлении новых.
Автоматизация генерации HTML-кода формы и проверки полученных данных и введение фильтрации HTML-спецсимволов на данном этапе позволяет избежать ряда наиболее типичных ошибок: некорректного вывода значений, содержащих HTML-спецсимволы, в полях формы и внедрение JavaScript для реализации кросссайтового скриптинга (также называемого XSS-атаками). Тем не менее, следует предусмотреть также и ситуации, когда HTML-код должен разрешаться для отдельно взятых полей формы (или его фильтрация должна проводиться в основной программе при каких-либо дополнительных условиях, например, при определенном уровне доступа пользователя).
Для проверки правильности заполнения поля на JavaScript в редакторе форм необходимо задать только условие и возращаемую в случае ошибки строку с сообщением об ошибке. Если поле заполнено правильно, возвращаемая строка должна быть пуста. Заголовок функции генерируется функциями XPDK, при этом форма, для которой производится проверка, передается как параметр self. Важно отметить, что проверка на JS производится дважды: первый раз - когда курсор покидает проверяемое поле (событие onBlur) - в этом случае меняется цвет рамки поля (по умолчанию на зеленый - если ошибок не найдено, и на красный - если ошибки возникли, но эти цвета можно переопределить через глобальные переменные $color_error и $color_ok), а второй раз - при нажатии кнопки отправит, при этом в случае ошибки выводится сообщение об ошибке и отправка формы отменяется, а курсор переставляется в первое поле с ошибкой.
Приведем конктретный пример: пусть в форме имеется поле f_name, которое не должно быть пустым. В этом случае в поле "код JavaScript для проверки" в XPDK-редакторе достаточно написать следующее: if (self.f_name.value=="") { return "Имя не может быть пустым!"; }
Все остальное сгенерирует XPDK, и в итоге для проверки получится следующая функция:
function f_name_chk(self) {
if (self.f_name.value=="") { return "Имя не может быть пустым!"; }
return "";
}
Т.е. для проверки нужно обрабатывать только ошибочные ситуации, ситуация, когда все Ok, предусмотрена по умолчанию.
Аналогично производится проверка и на стороне сервера на PHP, однако в PHP-функцию для проверки данные формы передаются в виде хеша с именем $data, причем передача осуществляется по ссылке, т.е. имеется возможность не только выводить сообщения об ошибках, но и изменять данные, например, на значения по умолчанию. Таким образом, в XPDK-редакторе для проверки описанной выше сиутации на PHP достаточно написать: if (!$data['fd_name']) error("Имя не может быть пустым!");
Так как прием данных из формы производится в хеш-массив, ключи которого совпадают с именами полей формы, а при извлечении данных из БД предусмотрена функция db_fetch_array, которая извлекает данные в хеш-массив, у которого ключи совпадают с именами столбцов, то имеет смысл сделать так, чтобы имена полей формы совпадали с именами столбцов в БД, так как в этом случае не потребуется каких-либо дополнительных действий по установлению соответствия между полями и столбцами.
В этом случае также полезными окажутся функции для более высокого уровня работы с БД, которые будут формировать готовые SQL-запросы вида INSERT и UPDATE с заданным условием для указанных таблиц с учетом всех полей, имеющихся в хеш-массиве и сразу же выполнять эти запросы. (Именно здесь и проявляется главное достоинство принципа отделения информации о полях от кода программы: в главной программе вообще нигде не требуется указывать полный список полей формы или базы данных!)
Однако здесь возникает проблема: форма может содержать поля, данные из которых требуется поместить в разные таблицы. В этом случае на помощь приходит принцип префиксного именования столбцов: предусмотрим в функциях, которые будут осуществлять вставку/изменение данных в базе, возможность отбирать только те ключи хеша, которые начинаются с заданного префикса. В этом случае для сохранения данных в несколько разных таблиц достаточно будет вызвать функцию сохранения несколько раз, каждый раз указывая свою таблицу и соответствующий ей префикс.