Основы PHP
  Что такое PHP?
  Возможности PHP
  Преимущества PHP
  История развития
  Что нового в PHP5?
  «Движок» PHP
  Переход на PHP 5.3
New Переход на PHP 5.6
  Введение в PHP
  Изучение PHP
  Основы CGI
  Синтаксис PHP
  Типы данных PHP
  Переменные в PHP
  Константы PHP
  Выражения PHP
  Операторы PHP
  Конструкции PHP
  Ссылки в PHP
  PHP и ООП
  Безопасность
  Функции PHP
  Функции по категориям
  Функции по алфавиту
  Стандартные функции
  Пользовательские
  PHP и HTTP
  Работа с формами
  PHP и Upload
  PHP и Cookies
  PHP и базы данных
  PHP и MySQL
  Документация MySQL
  Учебники
  Учебники по PHP
  Учебники по MySQL
  Другие учебники
  Уроки PHP
  Введение
  Самые основы
  Управление
  Функции
  Документация
  Математика
  Файлы
  Основы SQL
  Дата и время
  CURL
  Изображения
  Стили
  Безопасность
  Установка
  Проектирование БД
  Регулярные выражения
  Подготовка к работе
  Быстрый старт
  Установка PHP
  Установка MySQL
  Конфигурация PHP
  Download / Скачать
  Скачать Apache
  Скачать PHP
  Скачать PECL
  Скачать PEAR
  Скачать MySQL
  Редакторы PHP
  Полезные утилиты
  Документация
  PHP скрипты
  Скачать скрипты
  Инструменты
  PHP в примерах
  Новости портала
 Главная   »  Сборник статей
 
 

Totally XMLed Forms

Автор: Дмитрий Лебедев

Проект по созданию универсального обработчика форм для PHP, основанный на использовании XML-технологий.

В анонсах заметок я обещал написать про обработчики форм. Были какие-то наброски, но в основном теоретизирование. Серьёзный результат получился, когда встала необходимость сделать проект с большим количеством форм. Вылилось это в написание своего собственного обработчика, название которого вынесено в заголовок.

Опыт

Я смотрел чужие обработчики (честно!), но ни один не меня устроил. Конечно, по большому счёту, чужие программы никого не устраивают. Не так переменные называются, не такое взаимодействие. Узкая функциональность (а некоторые предлагают писать свой код внутрь класса - издеваются!), либо, наоборот, слишком обширная (большой комбайн, который перемалывает все мыслимые на свете конструкции, но чего-то нужного именно тебе в нём нет). Понятно, что такие несостыковки - это мелкие капризы, которые решаются поиском и сравнением разных классов и компромиссным выбором между ними.

Кое-кто в подобных ситуациях начинает писать своё собственное (класс шаблона, заменитель XPath и XSLT. Понятно, что это лишняя работа и изобретение велосипеда. На написание своего приложения уходит больше времени, чем на освоениче и незначительное приспособление чужого, готового (естественно, чем глубже изменения вы хотите внести в чужое, тем больше времени это тратит по сравнению с временем написания своего).

У меня ситуация была совсем другая, и я воплощал в цифру другую концепцию.

Проблема первая: гибкость класса. Вот понадобилось мне сделать каталог (да, да, есть чужие, я знаю, мне нужен собственный, у меня каталог для внутреннего пользования локальной сети, там всё сложнее). Решил я, что по-хорошему надо сделать расширенный поиск с вводом ключевых слов, выбором категорий (которых немного), и такой специфической фишкой как указание хоста, ресурсы которого надо показать. Остальные функции просмотра каталога - поиск, рубрики и хост - являются элементами множества расширенного поиска, и, естественно хотеть повесить их на этот же скрипт.

Писать php-код вроде "if (isset($HTTP_POST_VARS["bla-bla-bla"]) || isset($HTTP_POST_VARS["bla-bla-bla"])" мне обрыдло так, что ни пером описать. Надеясь увидеть класс, который позволит это описывать несколькими простыми операциями, скачиваю класс Forms generation and validation. Сложность первая: читаю документацию и не вижу, как можно сделать проверку правильности заполнения формы с условием "или" для моих трех элементов. Нельзя так сделать! Можно объявить элементы, которые надо проверять, и если все заполнены правильно, то и вся форма считается правильной. Если же хотя бы один заполнен неправильно - и вся форма считается неправильной. Можно не объявлять ни одного элемента - тогда никакой проверки. И никак иначе.

Ещё одна странность: есть типы операций проверки полей. То есть можно написать проверять поле как email, проверять как логин и т.д. Радует, что автор заботится о пользователях, но по-моему, эта забота не к месту. Случаев разных может быть много, и на всех их специальных функций проверки не напасёшься. Одним словом, гибкость движка в классе "Forms generation and validation" подменена набором частных случаев.

Наконец, третья неприятность: форма описывается ассоциативным массивом! Это самый неудобный формат, какой только можно было придумать. Чтобы можно было читать эти формы, придётся писать обработчик, перегоняющий HTML (или другой формат) в ассоциативные массивы. Итак, класс отправляется в "отстой". :)

Я смотрел и другие классы. Честно. Например phpLonghorn... простите, phpLoginForm :) Дмитрия Бородина. Размах впечатляет. В принципе, тем, кто не пользуется X-технологиями, этого комбайна может хватить за глаза так же как Smarty хватит для сайта, на котором не используется формат XML. Однако чувствуется, что класс не очень далеко ушёл от предыдущего. Посмотрев ещё пару классов, я понял, что до моего простора небесной мысли всем далеко, и взялся за написание своего формообработчика.

Концепция

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

Второй шаг. Все XML-обработчики поддерживают работу с выражениями XPath. Эти выражения описывают не только пути к узлам документа (нодсеты), но могут выдавать строковые результаты и даже булевые значения. Поэтому вместо того чтобы писать собственный анализатор данных, я сделал специальный элемент триггер, в который пишется выражение XPath, а уж пользователь сам придумает выражение той сложности, какой ему нужно. При анализе формы в документ вставляются полученные данные, затем выполняются эти выражения.

Некоторые операции проверки данных пришлось вынести в отдельные конструкции. Вызов пользовательских функций реализован через специальный элемент, в атрибутах которого указывается имя функции и путь XPath, куда нужно писать результат (вот вам и фильтры), дети элемента содержат аргументы функции (тоже выражения XPath).

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

Воплощение

Скачать последнюю версию можно с здесь. Сейчас проект находится в стадии альфы, потому что тестировался мало, и одна важная функция ждёт внесения в проект (речь об объявлении параметров специальной функцией, т.к. сейчас это можно делать только непосредственно добавляя узлы к корню документа).

Проект состоит из DTD-схемы документа формы, php-класса для работы с ним, XSLT-стиля для трансформации элементов формы TXF в обычную HTML-форму и подробная документация. Документация и комментарии кода написаны по-английски.

Пример использования класса. TXF-документ формы:

<txf:form name="friends_details" suggest-method="post" receive-method="post">
    <!-- during checking values will be inserted in child nodes to txf:input -->
    <txf:input name="birth_year" type="text" size="4" maxlength="4"/>
    
    <!-- it will look like this:
    <txf:input name="birth_year"><value>1980</value></txf:input> -->

    <txf:input name="phone" type="text" size="15" maxlength="10"/>
    <txf:input type="submit" value="Send"/>

    <txf:rule>
        <txf:logic type="and">
           <txf:trigger test="/txf:form/txf:input[@name = 'birth_year']/value > 1950 
           and /txf:form/txf:input[@name = 'birth_year']/value < 1990"/>
           <txf:check type="regexp" haystack="/txf:form/txf:input[@name = 'phone']/value" 
           needle="~(\+\d+ *\d+ *|)\d+~"/>
        </txf:logic>
    </txf:rule>
</txf:form>

Скрипт, обрабатывающий эту форму:

<?php
include_once("TXF.php");

$form = TXF::create("form_file.txf");

if ($form->error())
	die($form->error());

if ($form->submit_check())
{
	$form->append_values();
	$status = $form->get_status();
}

if ($status)
{
	// Work with data
}
else
{
	// Output form to submit
}
?>

Это случай достаточно простой формы, но класс может обрабатывать и более сложные - с массивами элементов управления, формы ленточного типа и даже формы, для которых требуется несколько вариантов действий (кроме простых - правильно заполнена/неправильно).

 
 » Обсудить эту статью на форуме

 
 Сборник статей 
 Содержание раздела 
Есть еще вопросы или что-то непонятно - добро пожаловать на наш  форум портала PHP.SU 
 

 
Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS