Totally XMLed Forms
Project for universal PHP-forms handler creation which is based on usage of XML-technologies.
In the articlesí announces I promised to write about form handlers. I had some sketches but they were mostly theoretical. Serious result was got when I faced the necessity to make a project with great number of forms. It resulted into writing of my own handler which name is made into the title.
I looked through other handlers (honestly!) but none of them suited me. Of course, by the highest standards otherís programs suit no one. Variable are called wrong, interaction is wrong too. Narrow functionality (some offer to write your code into a class Ė it must be a joke!) or conversely too wide one (big combine which mills all the possible constructions but nevertheless it lacks something which is necessary personally for you). Itís clear that such non-coincidences are little whims which are solved with search and comparison of different classes and compromise choice between them.
Someone in similar situations begins to write something of his own (sample class, substitute for XPath and XSLT). Clear, work like this is spare. Writing your own application takes longer time than mastering and slight adaptation of otherís ready-made one (of course, the more changes you want to make, the more time it will take in comparison with time for writing of your own).
I had quite a different situation and I materialized into numbers other conception.
The first problem is flexibility of a class. I needed to make a catalogue (there are many otherís, I know, but I need one of my own; I have a catalogue for internal usage in the local area network, everything is more complicated there). I decided to make an advanced search with key words input, choice of categories (there is small number of them) and such specific feature as indication of the host which resources should be shown. The rest of the functions for catalogueís review such as search, rubrics and host are the elements of advanced search multitude and itís natural to want their placement on the same script.
I was extremely tired of writing PHP-code like "if (isset($HTTP_POST_VARS["bla-bla-bla"]) || isset($HTTP_POST_VARS["bla-bla-bla"])". Hoping to see a class which enables describing this with some simple operations I download class Forms generation and validation. The first difficulty: I read documentation and donít see how it is possible to do validation of form filling with Ďorí condition for my three elements. You mustnít do like this! You may declare elements which should be verified and if all of them are filled in correctly, the whole form is considered to be correct too. If only one of them is filled in incorrectly, the whole form is considered to be invalid. You may declare no elements at all; then you evade validation. There are no other variants.
Another oddity: there are types of operations for fieldsí checking. I.e. you may check a field as e-mail, as login and so on. Itís very nice of the author to care about users but such care seems to be out of place. There can be many different cases and itís impossible to have special validation functions for each of them. In other words, flexibility of a runner in the class "Forms generation and validation" is replaced here by set of particular cases.
And finally, the third annoyance: form is described by an associative massive! This is the mostly inconvenient format which only could be invented. To enable reading these forms youíll have to write a handler conversing HTML (or other format) into associative massive.
I have also looked through other classes. Having done this I understood that my thoughts can be followed by none of them and started writing my own form handler.
To begin with I was led by a wish not to create a plenty of different formats, handlers and scripts conversing one format into another. Thus Iíve chosen a format basing on XML for the form description and evaded writing my own format handler by writing a DTD-schedule and reloading all this into standard validator XML.
Second step. All the XML-handlers support work with Xpath expressions. These expressions describe not only paths to the documentís units (nodsets) but also can put out string results and even bull meanings. So instead of writing my own data analyzer I made a special trigger element into which XPath expression is written and a user can create an expression with such grade of difficulty that he needs. By the form analysis the data obtained are inserted into a document and then these expressions are accomplished.
We had to carry out some operations of data verification into separate constructions. Call of usersí functions is realized through a special element in which attributes name of the function and XPath are indicated where the result should be written (here are the filters); elementís children contain arguments of the function (also XPath expressions)
And finally, logical operators. Any complicated logical expression can be obviously presented as a tree-formed structure. XML is exactly the format for tree-formed structuresí recording and so it is logical having some Bull meanings which are shown up by triggers and functions to unite them by logical expressions written in the XML-format.
You can download the ultimate version here. Now the project is on alpha-stage because testing is not enough and one important function awaits its insertion into the project (we speak about declaring parameters by a special function as now it is possible only by direct nodes adding to the root of a document).
The project consists of DTD-scheme of a form document, PHP-class for working with it, XSLT-style for conversion of TXF-formed elements into ordinary HTML-form and detailed documentation.
Example of class usage. TXF-document of a form:
<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: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+~"/>
Script for handling of this form:
$form = TXF::create("form_file.txf");
$status = $form->get_status();
// Work with data
// Output form to submit
This is the case of a rather simple form but the more complicated ones can also be handled by the class. These are management elementsí massives, band type forms and even forms which need some variants of actions (except for the simple ones Ė correctly filled in/ incorrectly).