Используйте PHP для создания XForms: Часть 1. Создание библиотеки XForms на PHP (исходники)

Тайлер Андерсон

Знакомство с библиотекой XForms

XForms - это великолепный язык Web 2.0, обладающий потрясающими возможностями, благодаря которым разработчики могут создавать самые современные формы. Почему бы не использовать его вместе с PHP? PHP-разработчики в своей работе традиционно используют HTML, который в большинстве случаев ограничивает возможности создаваемых ими форм. Однако при использовании XForms необходимо учитывать ряд моментов: файл должен быть строго формата XHTML, который является обновленной версией HTML, при этом XML не допускает ошибок при написании кода (к таким ошибкам относятся и неправильные теги). Кроме того, для XForms существует определенный синтаксис, который в процессе знакомства с XForms может вызывать определенные сложности у тех PHP-разработчиков, которые только начинают изучать язык PHP.

В данной статье описывается процесс создания библиотеки XForms на PHP, к которой PHP-разработчики могут обращаться при создании элементов XForms. Это позволит новичкам быстрее изучить XForms, а более опытным разработчикам XForms быстрее внедрить PHP в свои Web-приложения. Это позволит также избежать непосредственного вывода кода XHTML в открытом виде, а вместо этого будет происходить обращение к библиотеке XForms для вывода необходимого вам кода XHTML. Все это существенно ускоряет время разработки, значительно снижая вероятность возникновения ошибок в конечном коде XHTML.

Для повторения примеров, рассматриваемых в данной статье, вам необходимы PHP5 и плагин Firefox XForms. При написании данных статей тестирование проводилось на WAMP5 Server Version 1.7.1 с установленными Apache 2 и PHP5.

Настало время перейти к созданию библиотеки.

Создание библиотеки

При создании библиотеки XForms на PHP мы будем использовать класс, в котором будут содержаться все данные памяти и локальные переменные. Это избавит нас от необходимости использования дополнительных переменных и связанной с ними путаницы в коде. Вначале нам необходимо будет объявить класс и локальные переменные, как показано в листинге 1.

Листинг 1. Объявление класса и локальных переменных

                
<?php

class xforms_lib{
    var $namespace;
    var $namespaceXforms;
    var $namespaceEvents;

...

}

?>

Запомните имя класса, поскольку оно понадобится нам в дальнейшем, когда мы начнем им пользоваться. Три переменных, представленных выше в листинге 1 , являются основными пространствами имен, которые мы будем использовать: основное пространство имен XHTML, пространство имен XForms и пространство имен Events.

Обратите внимание на то, что конструктор, представленный в листинге 2, а также все последующие методы входят в объявленный ранее класс, представленный в листинге 1.

Поскольку вы уже начали выше писать код, то сохраните его в файле с названием xforms_lib.php и поместите его в подкаталог того каталога, в котором находится ваш PHP-код (назовите этот каталог, например, lib).

Эти переменные класса, представленные в листинге 1, определены в конструкторе класса, представленном в листинге 2.

Листинг 2. Конструктор xforms_lib

                    
    function xforms_lib($ns, $nsxforms, $nsevents){
        $this->namespace = $ns;
        $this->namespaceXforms = $nsxforms;
        $this->namespaceEvents = $nsevents;
    }

Представленный выше конструктор принимает значения этих пространств имен и сохраняет их в классе. Это позволяет нам не вводить их в том случае, если, например, необходимо создать несколько файлов XHTML, используя при этом нашу библиотеку XForms на PHP.

Далее нам необходимо создать метод htmlTag, который будет использоваться для объявления открывающего тега HTML. Фактически данная функция будет просто выводить тег HTML: "<html xmlns="..." , ...>" (листинг 3).

Листинг 3. Открытие тега HTML

                
    function htmlTag($customNS='', $customNSnamespace=''){
        $xml = '<html';
        if($this->namespace != '')
            $xml .= ' xmlns="'.$this->namespace.'"';
        if($this->namespaceXforms != '')
            $xml .= ' xmlns:xforms="'.$this->namespaceXforms.'"';
        if($this->namespaceEvents != '')
            $xml .= ' xmlns:ev="'.$this->namespaceEvents.'"';
        if($this->customNS != '' && $this->customNSnamespace != '')
            $xml .= ' xmlns:'.$this->customNS.
                '="'.$this->customNSnamespace.'"';
        $xml .= ' >';
        return $xml;
    }

Функция, представленная в листинге 3, создает открывающий тег HTML, помещая значения переменных сред в необходимую позицию в данном теге. Метод htmlTag выводит код XHTML, представленный в листинге 4.

Листинг 4. Код XHTML, выводимый функцией htmlTag

                
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:xforms="http://www.w3.org/2002/xforms" 
      xmlns:ev="http://www.w3.org/2001/xml-events" >

Теперь можно начать создавать и другие функции, которые будут определять содержимое других тегов XHTML XForms. Посмотрите на функцию submissionTag, представленную в листинге 5. Вы будете использовать эту функцию для создания тега submission.

Листинг 5. Функция submissionTag

                
    function submissionTag($id, $action, $method = 'post', $ref='',
                           $instance = '', $replace = ''){
        $xml = '<xforms:submission id="'.$id.'" action="'.$action.
            '" method="'.$method.'"';
        if($ref != '')
            $xml .= ' ref="'.$ref.'"';
        if($instance != '')
            $xml .= ' instance="'.$instance.'"';
        if($replace != '')
            $xml .= ' replace="'.$replace.'"';
        $xml .= " />";
        return $xml;
    }

Обратите внимание на то, что данная функция использует два входных параметра: $id и $action . Как мы видим, запрос по умолчанию осуществляется методом post. Таким образом, первые три переменные ( $id , $action и $method ) возвращаются в качестве результата XHTML независимо от значений других переменных. Если ref, instance и replace определены, то они также будут возвращены XHTML в качестве результата. Передача данной функции только двух входных параметров: submissionTag('xformsTest', 'receive.php') приведет к возвращению следующего кода XHTML: <xforms:submission id="xformsTest" action="receive.php" method="post" />.

Далее нам предстоит создать функцию bindTag, представленную в листинге 6. С помощью данной функции вы можете создавать привязку переменных к тегам, подставляя соответствующие параметры функции.

Листинг 6. Создание функции bindTag

                
    function bindTag($nodeset, $relevant = '', $calculate = '',
                     $required = ''){
        $xml = '<xforms:bind nodeset="'.$nodeset.'"';
        if($relevant != '')
            $xml .= ' relevant="'.$relevant.'"';
        if($calculate != '')
            $xml .= ' calculate="'.$calculate.'"';
        $xml .= " />";
        return $xml;
    }

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

Далее вам предстоит выводить тег dispatch. Это можно сделать с помощью PHP-кода, представленного в листинге 7. Используйте эту функцию для получения тега dispatch, сгенерированного на основе введенных входных параметров.

Листинг 7. Функция dispatchTag

                

    function dispatchTag($name, $target){
        $xml = '<xforms:dispatch';
        if($name != '')
            $xml .= ' name="'.$name.'"';
        if($target != '')
            $xml .= ' target="'.$target.'"';
        $xml .= " />";
        return $xml;
    }

Для использования данной функции необходимо указать два параметра: name и target. Их наличие позволит инициировать события XForms, например, xforms-submit, используемое для отправки элементов, определенных параметром name, по адресу, указанному в параметре target.

Функция loadTag может использоваться для перенаправления на другие страницы или для отображения всплывающих страниц (для этого необходимо передать параметр 'new' в переменную $show ). Взгляните на код, представленный в листинге 8. С помощью данной функции вы сможете создавать "на лету" теги load в вашем PHP-коде.

Листинг 8. Функция loadTag

                
    function loadTag($resource = '', $ref = '', $show='replace'){
        $xml = '<xforms:load show="'.$show.'"';
        if($ref != '')
            $xml .= ' ref="'.$ref.'"';
        else if($resource != '')
            $xml .= ' resource="'.$resource.'"';
        $xml .= " />";
        return $xml;
    }

Обратите внимание на то, что необходимо передавать функции только один из параметров $resource или $ref . Во второй части данной статьи вам предстоит добавить проверку того, что параметры $resource и $ref не заданы одновременно.

Далее создадим функцию insertTag, представленную в листинге 9. С помощью данной функции мы можем автоматически создавать теги insert в нашем PHP-коде в зависимости от данных, передаваемых функции.

Листинг 9. Функция insertTag

                
    function insertTag($nodeset, $at, $position = 'after'){
        $xml = '<xforms:insert nodeset="'.$nodeset.'" at="'.$at.
            '" position="'.$position.'" />';
        return $xml;
    }

Данная функция имеет два обязательных параметра и один дополнительный параметр - $position .

Следующая функция setvalueTag использует два входных параметра, как показано в листинге 10. С помощью данной функции вы сможете создавать теги setvalue.

Листинг 10. Функция setvalueTag

                
    function setvalueTag($ref, $value){
        $xml = '<xforms:setvalue ref="'.$ref.'" value="'.$value.'" />';
        return $xml;
    }

Структура функции inputTag несколько отличается тем, что, как показано в листинге 11, в ней присутствует вложенный тег label. С помощью данной функции вы сможете довольно просто создавать поля ввода в вашем PHP-коде.

Листинг 11. Функция inputTag

                
    function inputTag($ref, $label = ''){
        $xml = '<xforms:input ref="'.$ref.'">';
        if($label != '')
            $xml .= '<xforms:label>'.$label.'</xforms:label>';
        $xml .= "</xforms:input>";
        return $xml;
    }

Обратите внимание на то, что единственно необходимым входным параметром является $ref , а если определена переменная $label , то вложенный тег label помещается в тег input, который будет показан рядом с полем ввода, отображая информацию о том, какие именно данные должны быть введены (например, 'Номер телефона: '). Ниже в разделе "Простой тест" вы увидите, как работает данная функция.

Далее создадим функцию outputTag, представленную в листинге 12. Она аналогична функции inputTag, но в отличие от нее данная функция позволяет вам довольно просто создавать теги output в вашем PHP-коде.

Листинг 12. Функция outputTag

                
    function outputTag($value){
        $xml = '<xforms:output value="'.$value.'">';
        $xml .= '</xforms:output>';
        return $xml;
    }

Эта довольно простая функция, предназначенная для отображения на экране значения переменной. Ее использование аналогично выводу кода HTML непосредственно на обычную Web-страницу. Отличие состоит в том, что с помощью данной функции можно динамически изменять отображаемую информацию в зависимости от реального содержимого XML, зависящего от параметра value данной функции.

Следующая функция select1Tag является более сложной для понимания. Взгляните на листинг 13. С помощью функции select1Tag вы можете теперь гораздо проще создавать элемент select1, не заботясь о правильности написания синтаксиса.

Листинг 13. Функция select1Tag

                
    function select1Tag($ref, $label, $itemArray, $itemset,
                        $appearance = 'minimal'){
        $xml = '<xforms:select1 ref="'.$ref.'" appearance="'.
            $appearance.'">';
        $xml .= '<xforms:label>'.$label.'</xforms:label>';
        if(is_array($itemset)){
            $xml .= '<xforms:itemset nodeset="'.$itemset['nodeset'].'">';
            $xml .= '<xforms:label ref="'.$itemset['label'].'" />';
            $xml .= '<xforms:value ref="'.$itemset['value'].'" />';
            $xml .= '</xforms:itemset>';
        }
        else if(is_array($itemArray))
            foreach($itemArray as $item){
                $xml .= '<xforms:item>';
                $xml .= '<xforms:label>'.$item['label'].'</xforms:label>';
                $xml .= '<xforms:value>'.$item['value'].'</xforms:value>';
                $xml .= '</xforms:item>';
            }
        $xml .= '</xforms:select1>';
        return $xml;
    }

Данная функция отображает полный тег select1. Если массив меток и значений будет введен в элемент $itemArray , то все они будут последовательно представлены в меню. Если затем будет введен itemset, то тогда его значение будет использоваться для заполнения содержимого меню.

Следующая функция, представленная в листинге 14, предназначена для ускорения вывода комментариев в результирующем коде XHTML.

Листинг 14. Функция comment

                
    function comment($comment){
        $xml = '<!-- '.$comment.' -->';
        return $xml;
    }

Здесь входной параметр $comment помещен между открывающим и закрывающим тегом комментария XHTML, после чего используется команда return.

Следующий метод instanceTag, представленный в листинге 15, возвращает целый экземпляр класса. Эта функция позволяет вам довольно просто создавать объявления экземпляров класса в вашем PHP-коде.

Листинг 15. Функция instanceTag

                
    function instanceTag($id = '', $instanceXML = '', $src = ''){
        $xml = '<xforms:instance';
        if($id != '')
            $xml .= ' id="'.$id.'"';
        if($src != '')
            $xml .= ' src="'.$src.'"';
        else if($instanceXML != ''){
            $xml .= '>'."\r\n";
            $xml .= $instanceXML;
            $xml .= "\r\n".'</xforms:instance>';
        }
        else
            $xml .= " />";
        return $xml;
    }

С помощью данной функции может быть введен экземпляр класса XML через параметр $instanceXML, либо может быть введена URL-ссылка через параметр $src . К экземпляру класса затем можно будет обращаться из других элементов XHTML по его идентификатору ( $id ).

Функция submitTag предназначена для вывода кнопки, при нажатии на которую осуществляется подтверждение введенных данных с передачей их по определенной URL-ссылке. Просмотрите листинг 16. С помощью данной функции вы сможете довольно просто соединить кнопки подтверждения с соответствующими тегами в вашем PHP-коде.

Листинг 16. Функция submitTag

                
    function submitTag($submission, $label='Submit', $ref = ''){
        $xml = '<xforms:submit submission="'.$submission.'"';
        if($ref != '')
            $xml .= ' ref="'.$ref.'"';
        $xml .= ' >';
        $xml .= '<xforms:label>'.$label.'</xforms:label>';
        $xml .= '</xforms:submit>';
        return $xml;
    }

Когда вы создаете тег submission, используя для этого функцию submissionTag, представленную в листинге 5, вы можете в качестве параметра $submission вводить тот $id , который использовали в листинге 5. Тем самым вы свяжете элемент submit с элементом submission.

Последние восемь функций предназначены для открытия и закрытия следующих тегов: action, repeat, model и trigger (листинг 17).

Листинг 17. Открытие и закрытие тегов action, repeat, model и trigger

                
    function actionTagOpen($event){
        $xml = '<xforms:action ev:event="'.$event.'">';
        return $xml;
    }

    function actionTagClose(){
        $xml = '</xforms:action>';
        return $xml;
    }

    function repeatTagOpen($nodeset, $id = ''){
        $xml = '<xforms:repeat nodeset="'.$nodeset.'"';
        if($id != '')
            $xml .= ' id="'.$id.'"';
        $xml .= ' >';
        return $xml;
    }

    function repeatTagClose(){
        $xml = '</xforms:repeat>';
        return $xml;
    }

    function modelTagOpen($id = ''){
        $xml = '<xforms:model';
        if($id != '')
            $xml .= ' id="'.$id.'"';
        $xml .= ' >';
        return $xml;
    }

    function modelTagClose(){
        $xml = '</xforms:model>';
        return $xml;
    }

    function triggerTagOpen($ref, $submission = '', $label = 'default'){
        $xml = '<xforms:trigger ref="'.$ref.'"';
        if($submission != '')
            $xml .= ' submission="'.$submission.'"';
        $xml .= ' >';
        return $xml;
    }

    function triggerTagClose(){
        $xml = '</xforms:trigger>';
        return $xml;
    }

Структура этих функций аналогична другим функциям, представленным ранее, за исключением того что они только открывают или закрывают теги, которые могут иметь от одного до нескольких вложенных элементов. Элемент model, например, может иметь несколько вложенных привязок, экземпляров класса, элементов submission и т.д. Вам необходимо обратить внимание на то, что функции xxxxTagOpen используются для открытия соответствующих XHTML-тегов. Например, функция modelTagOpen() возвращает тег <xforms:model>. Функции xxxxTagClose используются для закрытия соответствующих XHTML-тегов. Например, функция modelTagClose() возвращает тег </xforms:model>. Функции закрытия тегов вообще не принимают никаких параметров, в то время как функции открытия тегов больше похожи на другие функции, описанные ранее в данной статье, за исключением того, что определенный тег XHTML не закрывается сразу, а только открывается для того, чтобы можно было добавлять другие вложенные элементы перед закрытием соответствующего тега XHTML.

Далее нам предстоит рассмотреть доказательство работы изложенной выше идеи.

Простой тест

Теперь настало время протестировать в работе все то, что мы создали. Для начала создадим простой файл index.php, как показано в листинге 18.

Листинг 18. Тестовый файл для доказательства изложенной выше идеи

                
<?php
header("Content-Type: application/xhtml+xml; charset=UTF-8");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<?php
include('lib/xforms_lib.php');
$xformsDoc = new xforms_lib("http://www.w3.org/1999/xhtml",
                            "http://www.w3.org/2002/xforms",
                            "http://www.w3.org/2001/xml-events");

echo $xformsDoc->htmlTag();

?>
<head><title>XForms served via PHP</title>

<?php

 // начало отображения модели

$model1 = 'first';
$instance1 = 'firstInstance';
$xformsTestSubmit = 'xformsTest';
$instance1data = '<root xmlns=""><data1/></root>';

echo $xformsDoc->modelTagOpen($model1);

echo $xformsDoc->instanceTag($instance1, $instance1data);

echo $xformsDoc->submissionTag($xformsTestSubmit,
                               "receive.php", 'post');

echo $xformsDoc->modelTagClose();

?>

</head><body>

<?php

 // начало отображения формы

echo $xformsDoc->inputTag("instance('$instance1')//data1", 'input1: ');

echo $xformsDoc->submitTag($xformsTestSubmit);

?>

</body>
</html>

Поскольку это PHP-файл, то необходимо сообщить браузеру о том, что данные относятся к типу application/xhtml+xml. Это позволит Firefox правильно отобразить данные XForms. Вы сможете этого достичь с помощью функции заголовка PHP - header(). Далее обратите внимание на то, каким образом открывается тег HTML: создается новый объекта класса xforms_lib, которому передаются три пространства имен. Затем в четырех выражениях в разделе "// начало отображения модели," вы можете увидеть определение нескольких переменных, которые будут использоваться в качестве идентификаторов для различных объектов, подчиненных элементов и других данных XForms, а также для данных экземпляра класса. Именно здесь вы сможете убедиться в реальной эффективности использования PHP и XForms: в удобстве использования имен переменных, которые вы можете использовать и сохранять, или получать из баз данных при создании документа XForms.

Вы также можете увидеть использование функций modelTagOpen и modelTagClose: вначале открывается тег model, пишутся теги instance и submission, после чего тег model закрывается с помощью вызова функции modelTagClose.

В теле HTML теги input и submit отображаются путем вызова функций inputTag и submitTag соответственно (результат показан на рисунке 1).

Рисунок 1. Подтверждение работоспособности изложенных принципов
Рисунок 1. Подтверждение работоспособности изложенных принципов

Теперь создадим страницу для отображения представляемых данных (содержимое файла index.php было указано выше в листинге 18). Для этого создадим новый файл receive.php, содержимое которого представлено в листинге 19.

Листинг 19. Прием и отображение данных, введенных в форму

                
<?php

if (!isset($HTTP_RAW_POST_DATA))
   $HTTP_RAW_POST_DATA = file_get_contents("php://input");

echo str_replace('>', '><br />',
                 str_replace('<', '<', $HTTP_RAW_POST_DATA));

?>

Здесь из строки ввода данные принимаются с помощью сценария, после чего они отображаются на экране.

Введите что-нибудь в текстовое поле и нажмите кнопку submit. Например, если вы введете "testing testing 1 2 3", то будет выведен результат, представленный в листинге 20.

Листинг 20. Полученные данные

                
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xforms="http://www.w3.org/2002/xforms" 
             xmlns:ev="http://www.w3.org/2001/xml-events">
<data1>
testing testing 1 2 3</data1>
</root>

Прекрасно! Теперь прочтите раздел "Заключение", чтобы узнать о том, что вам еще предстоит сделать.

Заключение

Вы успешно создали библиотеку XForms на PHP, которая в дальнейшем будет вам помогать при разработке и создании содержимого XForms.

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


Страница сайта http://www.interface.ru
Оригинал находится по адресу http://www.interface.ru/home.asp?artId=18466