Автор Анна Евкова
Преподаватель который помогает студентам и школьникам в учёбе.

Использование SOAP

Содержание:

ВВЕДЕНИЕ

Актуальность работы. По всей видимости, с приходом новых технологий и стандартов, таких как XML и HTTP, Web-сервисы обеспечили себе место в пантеоне интернет-инноваций. Основную концепцию Web-сервисов можно проследить в США до середины 1960-х годов. В транспортной отрасли, например, в железнодорожных и судоходных компаниях, была представлена новая концепция обмена электронными данными между компьютерами, развившаяся далее в технологию EDI (Electronic Data Interchange – обмен электронными данными). Впервые я услышал о EDI от профессора бизнес-школы в 1980 году.

В 1996 году Национальный институт стандартов и технологий США анонсировал стандарт для EDI в издании Federal Information Processing Standards Publications (FIPS PUB 161-2). Согласно опубликованной спецификации, EDI является стандартом обмена строго отформатированными сообщениями между компьютерами. Обработка принимаемых сообщений осуществляется только компьютером, и эти сообщения обычно не предназначены для интерпретации человеком. Это именно то, чем занимаются Web-сервисы, за исключением того, что в середине 1960-х годов не существовало XML, Интернета и World Wide Web.

Web-сервис – это программная система, предназначенная для поддержки межмашинных взаимодействий между вычислительными ресурсами по сети и использующая SOAP-сообщения (Simple Object Access Protocol), определенные консорциумом World Wide Web Consortium.

Simple Object Access Protocol (SOAP) – это простой расширяемый протокол, по которому происходит обмен структурированными и типизированными сообщениями в децентрализованной, распределенной сетевой среде. SOAP-сообщения записываются в формате языка Extensible Markup Language (XML) - простом и гибком текстовом формате, берущем начало от языка Standard Generalized Markup Language (SGML), который был разработан организацией International Organization for Standardization (ISO 8879:1986).

Цель работы – рассмотреть использование SOAP.

Задачи:

- рассмотреть теоретические аспекты использования SOAP;

- провести анализ использования SOAP;

- описать практическую работу с SOAP в PHP .

Объект исследования – протокол обмена SOAP.

Предмет исследования – применение протокола обмена.

Методы исследования – анализ, обобщение полученных результатов.

Структура работы состоит из введения, трех глав, заключения, списка литературы.

1. Теоретические аспекты использования SOAP

1.1 Основные понятия SOAP

SOAP - протокол обмена структурированными сообщениями в распределённой вычислительной среде[1]. Поддерживается консорциумом W3C.

Протокол SOAP создан в 1998 году командой разработчиков под руководством Дейва Винера (Dave Winer), работавшей в корпорации Microsoft и фирме Userland, но затем передан в консорциум W3C[3].

Последняя версия стандарта на сегодняшний день - SOAP 1.2. В версии 1.1 SOAP расшифровывался как Simple Object Access Protocol — простой протокол доступа к объектам. Это название отражало его первоначальное назначение — обращаться к методам удаленных объектов. Сейчас назначение SOAP изменилось, поэтому разные разработчики предлагали свои варианты расшифровки. Поэтому в версии 1.2 аббревиатуру решили никак не расшифровывать.

Протокол SOAP не различает вызов процедуры и ответ на него, а просто определяет формат послания (message) в виде документа XML[4]. Послание может содержать вызов процедуры, ответ на него, запрос на выполнение каких-то других действий или просто текст.

Спецификацию SOAP не интересует содержимое послания, она задает только его оформление.

SOAP основан на языке XML и расширяет некоторый протокол прикладного уровня — HTTP, FTP, SMTP и т.д. Как правило чаще всего используется HTTP. Вместо использования HTTP для запроса HTML-страницы, которая будет показана в браузере, SOAP отправляет посредством HTTP-запроса XML-сообщение и получает результат в HTTP-отклике. Для правильной обработки XML-сообщения процесс-«слушатель» HTTP (напр. Apache или Microsoft IIS) должен предоставить SOAP-процессор, или, другими словами, должен иметь возможность обрабатывать XML.

SOAP является самой главной частью технологии Web-сервисов. Он осуществляет перенос данных по сети из одного места в другое.[5]

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

SOAP – это базовая однонаправленная модель соединения, обеспечивающая согласованную передачу сообщения от отправителя к получателю, потенциально допускающая наличие посредников, которые могут обрабатывать часть сообщения или добавлять к нему дополнительные элементы[6]. Спецификация SOAP содержит соглашения по преобразованию однонаправленного обмена сообщениями в соответствии с принципом «запрос/ответ», а также определяет как осуществлять передачу всего XML-документа.

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

Рисунок 1 – SOAP[7]

SOAP-сообщение представляет собой XML-документ; сообщение состоит из трех основных элементов: конверт (SOAP Envelope), заголовок (SOAP Header) и тело (SOAP Body)[9] (рисунок 2).

Рисунок 2. Структура SOAP сообщения[8]

Пример SOAP сообщения[6]:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"

xmlns:t="www.example.com">

<SOAP-ENV:Header>

</SOAP-ENV:Header>

<SOAP-ENV:Body>

<t:CurrentDate>

<Year>2011</Year>

<Month>February</Month>

<Day>12</Day>

<Time>18:02:00</Time>

</t:CurrentDate>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

Конверт (SOAP Envelope). Является самым «верхним» элементом SOAP сообщения. Содержит корневой элемент XML-документа. Описывается с помощью элемента Envelope с обязательным пространством имен http://www.w3.org/2003/05/soap-envelope для версии 1.2 и http://schemas.xmlsoap.org/soap/ для версии 1.1.

У элемента Envelope могут быть атрибуты xmlns, определяющие пространства имен, и другие атрибуты, снабженные префиксами[10].

Envelope может иметь необязательный дочерний элемент Header c тем же пространством имен — заголовок[11]. Если этот элемент присутствует, то он должен быть первым прямым дочерним элементом конверта.

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

Версия 1.1 позволяла после тела сообщения записывать произвольные элементы, снабженные префиксами. Версия 1.2 это запрещает.

Элементы Header и Body могут содержать элементы из различных пространств имен.

Конверт изменяется от версии к версии. SOAP-процессоры, совместимые с версией 1.1, при получении сообщения, содержащего конверт с пространством имен версии 1.2, будут генерировать сообщение об ошибке. Аналогично для SOAP-процессоров, совместимых с версией 1.2. Ошибка — VersionMismatch.[12]

Заголовок SOAP (SOAP Header). Первый прямой дочерний элемент конверта. Не обязательный. Заголовок кроме атрибутов xmlns может содержать 0 или более стандартных атрибутов[13]:

• encodingStyle

• actor (или role для версии 1.2)

• mustUnderstand

• relay

Атрибут encodingStyle. В SOAP-сообщениях могут передаваться данные различных типов (числа, даты, массивы, строки и т.п.). Определение этих типов данных выполняется в схемах XML (обычно — XSD). Типы, определенные в схеме, заносятся в пространство имен, идентификатор которого служит значением атрибута encodingStyle. Атрибут encodingStyle может появиться в любом элементе SOAP-сообщения, но версия SOAP 1.2 запрещает его появление в корневом элементе Envelope. Указанное атрибутом encodingStyle пространство имен будет известно в том элементе, в котором записан атрибут, и во всех вложенных в него элементах. Какие-то из вложенных элементов могут изменить пространство имен своим атрибутом encodingStyle.

Стандартное пространство имен, в котором расположены имена типов данных SOAP 1.1, называется http://schemas.xmlsoap.org/soap/encoding/. У версии 1.2 - http://www.w3.org/2003/05/soap-encoding. Идентификатор того или иного пространства имен, в котором определены типы данных, обычно получает префикс enc или SOAP-ENC.[14]

Атрибут actor. Тип данных URI. Задает адрес конкретного SOAP-сервера, которому предназначено сообщение.

SOAP-сообщение может пройти через несколько SOAP-серверов или через несколько приложений на одном сервере[15]. Эти приложения выполняют предварительную обработку блоков заголовка послания и передают его друг другу. Все эти серверы и/или приложения называются SOAP-узлами (SOAP nodes). Спецификация SOAP не определяет правила прохождения послания по цепочке серверов. Для этого разрабатываются другие протоколы, например, Microsoft WS-Routing.

Атрибут actor задает целевой SOAP-узел — тот, который расположен в конце цепочки и будет обрабатывать заголовок полностью[12]. Значение http://schemas.xmlsoap.org/soap/actor/next атрибута actor показывает, что обрабатывать заголовок будет первый же сервер, получивший его. Атрибут actor может встречаться в отдельных блоках заголовка, указывая узел-обработчик этого блока. После обработки блок удаляется из SOAP-сообщения.

В версии 1.2 атрибут actor заменен атрибутом role, потому что в этой версии SOAP каждый узел играет одну или несколько ролей. Спецификация пока определяет три роли SOAP-узла:

• Роль http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver играет конечный, целевой узел, который будет обрабатывать заголовок.

• Роль http://www.w3.org/2003/05/soap-envelope/role/next играет промежуточный или целевой узел. Такой узел может играть и другие, дополнительные роли.

• Роль http://www.w3.org/2003/05/soap-envelope/role/none не должен играть ни один SOAP-узел.

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

Значением атрибута role может быть любая строка URI, показывающая роль узла, которому предназначен данный блок заголовка[11]. Значением по умолчанию для этого атрибута служит пустое значение, то есть, просто пара кавычек, или строка URI http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver.

Значение атрибута role показывает, что блок должен быть обработан узлом, играющим роль, определенную такой же строкой[5].

Атрибут mustUnderstand. Тип данных - boolean. По умолчанию 0. Если значение равно 1, то SOAP-узел при обработке элемента обязательно должен учитывать его синтаксис, определенный в схеме документа, или совсем не обрабатывать сообщение. Это повышает точность обработки сообщения.

В версии SOAP 1.2 вместо цифр нужно писать true или false[8].

Атрибут relay. Тип данных — boolean. Показывает, что заголовочный блок, адресованный SOAP-посреднику, должен быть передан дальше, если он не был обработан. Необходимо отметить, что если заголовочный блок обработан, правила обработки SOAP требуют, чтобы он был удален из уходящего сообщения. По умолчанию, необработанный заголовочный блок, предназначенный роли, которую исполняет SOAP-посредником, должен быть удален перед отправкой сообщения.

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

В блоках заголовка могут быть атрибуты role, actor и mustUnderstand[4]. Действие этих атрибутов относится только к данному блоку. Это позволяет обрабатывать отдельные блоки заголовка промежуточными SOAP-узлами, чья роль совпадает с ролью, указанной атрибутом role. Ниже дан пример такого блока[5]:

<env:Header>

<t:Transaction xmlns:t="http://example.com/transaction"

env:role="http://www.w3.org/2003/05/soapenvelope/

role/ultimateReceiver"

env:mustUnderstand="true">

</t:Transaction>

</env:Header>

Элементы, вложенные в блоки заголовка, уже не называются блоками. Они не могут содержать атрибуты role, actor и mustUnderstand.

Тело SOAP (SOAP Body). Элемент Body обязательно записывается сразу за элементом Header, если он есть в сообщении, или первым в SOAP-сообщении, если заголовок отсутствует[3]. В элемент Body можно вложить произвольные элементы, спецификация никак не определяет их структуру.

Определен только один стандартный элемент, который может быть в теле сообщения - Fault, содержащий сообщение об ошибке.

1.2 Модель обработки

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

Рисунок 2. Сложный обмен SOAP сообщениями[10]

Посредник располагается между начальным отправителем и конечным получателем и перехватывает SOAP сообщения. Посредник работает одновременно и как SOAP отправитель, и как SOAP получатель[5]. Промежуточные узлы делают возможным разрабатывать некоторые интересные и гибкие сетевые архитектуры, на которые можно воздействовать содержимым сообщения. Маршрутизация SOAP сообщений является хорошим примером того, что значительно усиливает значимость SOAP посредников.

Обрабатывая сообщение, SOAP узел берет на себя одну или более ролей, которые влияют на то, как обрабатываются SOAP заголовки[1]. Ролям даются уникальные имена (в форме URI), таким образом, они могут быть идентифицированы во время обработки. SOAP узел, получив сообщение для обработки, сначала должен определить, какие роли он будет выполнять. Для этого он может проверить SOAP сообщение.

Как только он определится с ролями, которые будет выполнять, SOAP узел должен обработать все обязательные заголовки (отмеченные mustUnderstand="1"), направленные на одну из его ролей[14]. Также SOAP узел может выбрать для обработки любой необязательный заголовок (отмеченный mustUnderstand="0"), направленный на одну из его ролей.

SOAP 1.1 определяет только одну роль - http://schemas.xmlsoap.org/soap/actor/next (next для краткости)[4]. Каждый SOAP узел должен принять роль next. Таким образом, когда SOAP сообщение приходит в любой данный SOAP узел, узел должен обработать все обязательные заголовки, нацеленные на роль next, и он может обработать необязательные заголовки, также нацеленные на роль next. Кроме next, SOAP 1.2 определяет еще несколько ролей, приложениям разрешено также определять собственные роли.

SOAP заголовки нацеливаются на конкретные роли с помощью глобального атрибута actor (в SOAP 1.2 этот атрибут назван role). Если этого атрибута нет, заголовок по умолчанию нацеливается на конечного получателя. Следующее SOAP сообщение иллюстрирует, как использовать actor[10]:

<soap:Envelope

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">

<soap:Header>

<wsrp:path xmlns:wsrp="http://schemas.xmlsoap.org/rp"

soap:actor="http://schemas.xmlsoap.org/soap/actor/next"

soap:mustUnderstand="1"

>

...

Поскольку заголовок wsrp:path нацелен на роль next и помечен как обязательный (mustUnderstand="1"), первый SOAP узел, получающий это сообщение, должен обработать его в соответствии со спецификацией блока заголовка, в данном случае WS-Routing. Если SOAP узел разработан так, что не понимает обязательного заголовка, нацеленного на одну из его ролей, он должен сгенерировать SOAP ошибку с кодом состояния soap:MustUnderstand и прервать обработку[9]. Чтобы определить, что вызвало ошибку в прохождении сообщения, элемент SOAP Fault предоставляет дочерний элемент faultactor[8]. Значением атрибута faultactor является URI, который идентифицирует SOAP узел, вызвавший ошибку.

Если SOAP узел успешно обработал заголовок, требуется удалить этот заголовок из сообщения. SOAP узлам разрешено повторно вставлять заголовки, но это изменяет участников контракта – теперь заголовки targets между текущим и следующим узлами. Если SOAP узел оказывается конечным получателем, он также должен обработать и SOAP тело.

2. Анализ использования SOAP

2.1 Построение каталога товаров

Основная цель при создании каталога товаров сводится к программной реализации Web-интерфейса для взаимодействия с базой данных, при котором применяется входная аутентификация[12]. Для реализации этих функций необходимо обеспечить аутентификацию пользователя при входе в систему, как показано в листинге 1:

Листинг 1. PHP-сценарий для входа в систему.

<?php

require_once('book_sc_fns.php');

do_html_header('Администрирование');

display_login_form();

do_html_footer();

?>[10]

Данный сценарий требует подключения ряда функций, перечисленных в листинге 2.

Листинг 2. Подключение необходимых функций.

<?php

include_once('db_fns.php');

include_once('data_valid_fns.php');

include_once('output_fns.php');

include_once('book_fns.php');

include_once('user_auth_fns.php');

include_once('admin_fns.php');

include_once('order_fns.php');

?>[15]

Идентификация администратора после входа в систему осуществляется через переменную HTTP-сеанса admin_user и функцию check_admin_user(). Как только пользователь входит в систему с полномочиями администратора, он получает возможность изменить свой пароль или выйти из системы. Для добавления в каталог новой категории товаров или книги используются сценарии.

Если в сценарий передается массив с данными о книге, то форма переходит в режим редактирования и поля заполняются информацией о редактируемой книге, загруженной из базы, как показано ниже[11]:

<input type='text' name='price'

value="<?php echo $edit?$book['price']:''; ?>">

При этом на странице появляется кнопка для удаления книги. По сути, при редактировании видны две кнопки – одна существует для редактирования данных о книге, другая несет в себе функцию полного удаления книги вообще. Нажатие этих кнопок приводит к вызову соответствующих PHP-сценариев для обновления информации о книге и ее удалении.

Функциональность для управления категориями товаров построена по схожему принципу[14]. При попытке удаления категории проверяется, есть ли в ней книги. Если это так, то удалить категорию невозможно, если же категория пуста, то она может быть удалена из каталога. При этом минимизируется опасность случайного удаления информации.

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

Существуют два метода отслеживания товаров, выбранных посетителями. Первый – это помещение выбранных элементов в базу данных, а второй – манипулирование переменными HTTP-сеанса. Использование переменных HTTP-сеанса для отслеживания выбираемых товаров гораздо проще в реализации, так как не требует постоянного обращения к базе данных. Также такой подход позволяет избежать загромождения базы ненужными данными в процессе работы, так как отдельные посетители могут просто просматривать магазин, что-то выбирать, но ничего не покупать. И если каждый раз их действия будут вносить изменения в базу данных, то это приведет к чрезмерным накладным расходам.[8] Поэтому использование переменных HTTP-сеанса будет наилучшим выбором для решения данной задачи. При этом, когда пользователь завершит работу с каталогом и произведет окончательный расчет, эта информация будет помещена в базу данных в виде записи, регистрирующей транзакцию. Помимо этого, эти данные могут отображаться в другом месте на Web-странице, чтобы пользователь в любой момент времени мог видеть стоимость заказанных им товаров.

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

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

Кроме платежной системы и других элементов потребуется административный интерфейс для реализации таких возможностей, как добавление, удаление и редактирование информации о книгах и категориях в базе данных.[5] Чаще всего приходится менять цену на товар, так как в магазинах регулярно проводятся специальные акции или сезонные распродажи. Это приводит к необходимости сохранения не только заказа клиента, но и цены, которая должна быть выплачена за выбранный товар. Отражение в записях только элементов заказа и текущей цены каждого элемента может существенно затруднить работу бухгалтерии.[4] Помимо этого, в такой ситуации при возврате или обмене товара клиенту, возможно, будут возвращены лишние денежные средства, если товары были приобретены по акции. Все это необходимо учесть при реализации системы.

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

2.2 Построение online-каталога товаров

Административный интерфейс позволяет входить в систему и добавлять новые книги и категории.[3] При этом самый простой способ реализовать возможность редактирования и удаления книг и категорий состоит в том, чтобы предоставить администратору отдельную версию сайта, отличную от той, которая доступна пользователю.[1] В этом случае администратор будет иметь возможность просматривать категории и книги, но вместо доступа к покупательской корзине он будет переходить к определенной книге или категории, а затем редактировать или удалять ее.

В данном контексте потребуется разработать некоторые сценарии так, чтобы они соответствовали требованиям и пользователей, и администратора. Поэтому тремя основными компонентами системы будут являться: каталог товаров, покупательская корзина вместе с обработкой заказа и административный интерфейс сайта.[6] Для этого потребуется создать набор библиотек, объединяющих фрагменты кода, отвечающие за вывод HTML, тем самым, отделив бизнес-логику от представления. Такой подход значительно упростит создание и сопровождение кода.

В листинге 1 приведен PHP-сценарий для титульной страницы каталога товаров[2].

Листинг 1. PHP-сценарий online-каталога

<?php

require ('book_sc_fns.php');

// для использования покупательской корзины необходимо запустить HTTP-сеанс

session_start();

do_html_header('Рады видеть Вас в магазине Книголюб!');

echo '<p>Пожалуйста, выберите категорию:</p>';

// извлечь категории из базы данных

$cat_array = get_categories();

// отобразить категории в виде ссылок на соответствующие страницы

display_categories($cat_array);

// если пользователь вошел в систему как администратор, вывести

// ссылки для добавления, удаления и редактирования категорий

if(isset($_SESSION['admin_user']))

{

display_button('admin.php', 'admin-menu', 'Меню администрирования');

}

do_html_footer();

?>

В листинге 2 приведены функции, отвечающие за отображение верхнего и нижнего колонтитулов:

Листинг 2. PHP-функции для отображения колонтитулов[7]

<?php

function do_html_header($title = '')

{

// вывод HTML-заголовка

// объявление переменных HTTP-сеанса

if(!$_SESSION['items']) $_SESSION['items'] = '0';

if(!$_SESSION['total_price']) $_SESSION['total_price'] = '0.00';

?>

<html>

<head>

<title><?php echo $title; ?></title>

</head>

<body>

<table width='100%' border=0 cellspacing = 0 bgcolor='#cccccc'>

<tr>

<td rowspan = 2>

<a href = 'index.php'>

<img src='images/Book-O-Rama.gif' alt='Магазин КНИГОЛЮБ' border=0

align='left' valign='bottom' height = 55 width = 325></a>

</td>

<td align = 'right' valign = 'bottom'>

<?php if(isset($_SESSION['admin_user']))

echo '&nbsp;';

else

echo 'Всего книг = '.$_SESSION['items'];

?>

</td>

<td align = 'right' rowspan = 2 width = 135>

<?php if(isset($_SESSION['admin_user']))

display_button('logout.php', 'log-out', 'Выход');

else

display_button('show_cart.php', 'view-cart', 'Показать корзину');

?>

</tr>

<tr>

<td align = right valign = top>

<?php if(isset($_SESSION['admin_user']))

echo '&nbsp;';

else

echo 'Общая сумма = $'.number_format($_SESSION['total_price'],2);

?>

</td>

</tr>

</table>

<?php

if($title)

do_html_heading($title);

}

function do_html_footer()

{

// вывод завершающих HTML-дескрипторов

?>

</body>

</html>

<?php

// дальше идут остальные функции, входящие в библиотеку

}

В листинге 3 рассматривается PHP-сценарий, реализующий самые важные элементы бизнес-процесса.

Листинг 3. Основной PHP-сценарий[8]

<?php

// использование переменной HTTP-сеанса в качестве корзины пользователя

session_start();

require_once('constants.php');

require_once('Product.php');

require_once('AmazonResultSet.php');

require_once('utilityfunctions.php');

require_once('bookdisplayfunctions.php');

require_once('cartfunctions.php');

require_once('categoryfunctions.php');

// массив с названиями входных параметров.

// они пройдут валидацию и будут трансформированы в глобальные переменные.

$external = array('action', 'ASIN', 'mode', 'browseNode', 'page', 'search');

// входные параметры могут быть получены через методы GET или POST.

foreach ($external as $e)

{

if(@$_REQUEST[$e])

$$e = $_REQUEST[$e];

else

$$e = '';

$$e = trim($$e);

}

// значения по умолчанию для глобальных переменных.

if($mode=='')

$mode = 'books'; // товар по умолчанию - книги

if($browseNode=='')

$browseNode = 53; // категория по умолчанию - 53 (бестселлеры)

if($page=='')

$page = 1; // страница по умолчанию - 1

// валидация входных параметров

if(!eregi('^[A-Z0-9]+$', $ASIN)) // ASIN - последовательность символов и цифр

$ASIN ='';

if(!eregi('^[a-z]+$', $mode)) // mode - последовательность символов

$mode = 'books';

$page=intval($page); // pages и browseNodes - числа

$browseNode = intval($browseNode);

$search = safeString($search);

if(!isset($_SESSION['cart']))

{

session_register('cart');

$_SESSION['cart'] = array();

}

// эти действия должны быть выполнены до того,

// как будет показан верхний раздел

addToCart($_SESSION['cart'], $ASIN, $mode);

if($action == 'deletefromcart')

deleteFromCart($_SESSION['cart'], $ASIN) ;

if($action == 'emptycart')

$_SESSION['cart'] = array();

// просмотр верхнего раздела

require_once ('topbar.php');

switch ($action)

{

case 'detail' :

showCategories($mode);

showDetail($ASIN, $mode);

break;

case 'addtocart' :

case 'deletefromcart' :

case 'emptycart' :

case 'showcart' :

echo '<hr /><h1>покупательская корзина</h1>';

showCart($_SESSION['cart'], $mode);

break;

case 'image' :

showCategories($mode);

echo '<h1>увеличенное изображение товара</h1>';

showImage($ASIN, $mode);

break;

case 'search' :

showCategories($mode);

echo "<h1>результат поиска '$search'</h1>";

showSearch($search, $page, $mode);

break;

case 'browsenode':

default:

showCategories($mode);

$category = getCategoryName($browseNode);

if(!$category||$category=='Best Selling Books')

{

echo '<h1>бестселлеры</h1>';

}

else

{

echo "<h1>бестселлеры в категории $category</h1>";

}

showBrowseNode($browseNode, $page, $mode) ;

break;

}

require ('bottom.php');

?>

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

Листинг 4. Используемые константы[9]

<?php

// это приложение будет работать по методу REST (XML поверх HTTP) или SOAP

define('METHOD', 'REST');

// константы для создания кэша

define('CACHE', 'cache'); // путь к кэшируемым файлам

define('ASSOCIATEID', 'webservices-20'); // установить ID

define('DEVTAG', 'DHBIBVFDMBJDL'); // установить DEVTAG

if(DEVTAG=='XXXXXXXXXXXXXX')

{

die ('необходимо зарегистрироваться для использования Web-служб Amazon

<a href = "https://associates.amazon.com/exec/panama/associates/

join/developer/application.html/ref=sc_bb_l_0/002">Amazon</a>

');

}

// закрытый список категорий товаров

$categoryList = array(5=>'Computers & Internet', 3510=>'Web Development',

295223=>'PHP', 17=>'Literature and Fiction',

3=>'Business & Investing', 53=>'Non Fiction',

23=>'Romance', 75=>'Science', 21=>'Reference',

6 =>'Food & Wine', 27=>'Travel',

16272=>'Science Fiction'

);

?>

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

3. Практическая работа с SOAP в PHP

Главным преимуществом технологии SOAP перед технологией XML-RPC является поддержка типов данных, которые могут определяться пользователем.[10] Эти типы данных могут быть описаны и проверены с помощью XML-схемы. Например, реализация PEAR SOAP обеспечивает автоматическое преобразование пользовательских типов в классы PHP.

Технология SOAP также является идеальным примером того, что простая идея не всегда означает простую реализацию.[11] SOAP сообщение состоит из конверта, содержащего заголовок и тело.[12] Имена всех элементов в SOAP-документе определены, что хотя и повышает надежность, но затрудняет восприятие получившегося XML-документа человеком. На верхнем уровне иерархии находится конверт (envelope), представляющий собой контейнер для SOAP-сообщения. Он располагается в пространстве имен xmlsoap, что, как правило, указывается в его полном имени и последующем объявлении пространства имен.

SOAP неявно использует язык XML-схемы (XML Schema), представляющий собой язык для определения и проверки структур данных на основе XML. Согласно стандарту пространство имен для элементов XML-документа описывается в отдельном файле, содержащим XML-схему и также являющимся XML-документом. В листинге 1 представлен пример реализации SOAP-клиента, предназначенного для работы с Web-службами.

Листинг 1. Вызов Web-службы с помощью SOAP

<?php

require_once 'SOAP/Client.php';

$url = 'http://soap.amazon.com/schemas2/AmazonWebServices.wsdl';

$client = new SOAP_Client($url, true);

class AuthorRequest implements SchemaTypeInfo {

public $author;

public $page;

public $mode;

public $tag;

public $type;

public $devtag;

public $sort;

public $variations;

public $locale;

public static function getTypeName()

{ return 'AuthorRequest';}

public static function getTypeNamespace()

{ return 'http://soap.amazon.com';}

}

// присвоить значения переменным

$authreq = new AuthorRequest;

$authreq->author = 'schlossnagle';

$authreq->mode = 'books';

$authreq->type = 'lite';

$authreq->devtag = 'D3J98F4T2LIT7G';

// создать экземпляр soap-клиента

$client->AuthorSearchRequest($authreq);

$params = array(

'author' => 'schlossnagle',

'page' => 1,

'mode' => 'books',

'tag' => 'webservices-20',

'type' => 'lite',

'dev-tag' => 'D7J91F8T2LIT7Н',

);

// вызов Web-службы

$result = $client->AuthorSearchRequest($authreq)->deserializeBody();

foreach ($result->Details as $detail) {

print "Title: $detail->ProductName, ASIN: $detail->Asin\n";

}

Протокол SOAP дополняется языком WSDL (Web Service Definition Language - язык определения Web-служб)[13]. Технология WSDL также представляет собой язык, основанный на XML, и используется для описания функциональности и способов взаимодействия с Web-службами. Язык WSDL также интенсивно использует пространства имен.

В PEAR, официальном хранилище пакетов для PHP, можно найти расширение для SOAP[14]. SOAP-расширение для PHP зависит от других пакетов, поэтому потребуется установить и используемые им пакеты.

Следует отметить, что для практической реализации Web-службы к классу, реализующему Web-службу (класс SOAP_SERVER), обычно требуется добавить код для установки значений параметров и реализацию бизнес-логики[15].

В листинге 2 рассматривается фрагмент функции browseNodeSearch, использующей протокол SOAP для вызова Web-службы компании Amazon.

Листинг 2. Фрагмент функции browseNodeSearch для работы с SOAP

function browseNodeSearch($browseNode, $page, $mode)

{

if(METHOD=='SOAP')

{

// инициализация soap-клиента

$soapclient = new soapclient(

'http://soap.amazon.com/schemas2/AmazonWebServices.wsdl',

'wsdl');

$soap_proxy = $soapclient->getProxy();

$parameters['mode']=$mode;

$parameters['page']=$page;

$parameters['type']='heavy';

$parameters['tag']=$this->assocID;

$parameters['devtag']=$this->devTag;

$parameters['sort']='+salesrank';

$parameters['browse_node'] = $browseNode;

// выполнение soap-запроса

$result = $soap_proxy->BrowseNodeSearchRequest($parameters);

// проверка на ошибки, возникшие в ходе выполнения запроса

if(isSOAPError($result))

return false;

// обработка полученных результатов

$this->totalResults = $result['TotalResults'];

foreach($result['Details'] as $product)

{

$this->products[] = new Product($product);

}

// освобождение использованных ресурсов

unset($soapclient);

unset($soap_proxy);

}

else

{

// выполнение запроса по технологи REST

}

return $this->products;

}

В представленном фрагменте кода не используется никаких вспомогательных функций, все выполняется «здесь и сейчас». SOAP-клиент выполняет все необходимые действия самостоятельно. При создании SOAP-клиента, ему передаются два параметра. Первый параметр содержит URL-адрес документа, а второй параметр сообщает клиенту тип этого документа (WSDL). В строке, представленной ниже[10]:

$soap_proxy = $soapclient->getProxy();

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

Вызвать Web-службу можно, просто используя прокси-класс и передав ему массив параметров, как показано ниже.

$result = $soap_proxy->BrowseNodeSearchRequest($parameters)[9];

При этом данные, хранящиеся в переменной result, представляют собой массив, записи из которого можно преобразовать в объекты типа Product и, в свою очередь, сохранить в массиве products класса AmazonResultSet.

Файлы с кэшированными запросами получают имена, основанные на значениях параметров, присутствующих в запросе. При такой реализации извлечение результирующего набора данных из кэша потребует доли секунды, а для реального выполнения запроса к удаленному Web-сайту потребовалось бы порядка 10-12 секунд.[8]

Кэширование начальной страницы. В этом разделе рассматривается организация кэширования для сайта, применяющего регистрацию пользователей и предоставляющего ряд служб. Представленный исходный код учитывает требования, предъявляющиеся к приложениям подобного рода. Для сложных и масштабных Web-сайтов обычно требуется обеспечить хорошую пропускную способность и одновременно сократить нагрузку на базу данных. Пример кода для реализации кэширования в подобных системах приведен в листинге 3.

Листинг 3. Организация кэширования для нагруженных Web-сайтов

<?php

require 'Project.inc';

try {

$name = $_GET[name];

if(!$name) {

throw new Exception();

}

$project = new Project($name);

}

catch (Exception $e) {

// при возникновении ошибки перенаправлять на этот адрес

header("Location: /index.php");

return;

}

$cache = new Cache::File(Project::get_cachefile($name));

$cache->begin();

?>

<html>

<title><?= $project->name ?></title>

<body>

<!-- шаблон содержания страницы -->

<table>

<tr>

<td>Author:</td><td><?= $project->author ?>

</tr>

<tr>

<td>Summary:</td><td><?= $project->short_description ?>

</tr>

<tr>

<td>Availability:</td><td><a href="<?= $project->file_url ?>">click here</a></td>

</tr>

<tr>

<td><?= $file->long_description ?></td>

</tr>

</table>

</body>

</html>

<?php

$cache->end();

?>

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

Таким образом, были рассмотрены вопросы, относящиеся к реализации SOAP-клиента на основе библиотеки PEAR::SOAP для вызова Web-служб, а также продемонстрированы несколько подходов к организации кэширования информации – как для результатов запросов, полученных от Web-служб, так и для простых HTML-страниц с динамическим содержимым, использующихся в приложениях с высоким уровнем нагрузки.

ЗАКЛЮЧЕНИЕ

В результате проделанной работы решены следующие задачи: рассмотрены теоретические аспекты использования SOAP; проведен анализ использования SOAP; описана практическая работа с SOAP в PHP.

SOAP расшифровывается как Simple Object Access Protocol (Простой Протокол Доступа к Объектам). SOAP в теперешней его форме – это метод удаленного вызова (RPC, Remote procedure Call) по сети.

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

Главным преимуществом технологии SOAP перед технологией XML-RPC является поддержка типов данных, которые могут определяться пользователем. Эти типы данных могут быть описаны и проверены с помощью XML-схемы. Например, реализация PEAR SOAP обеспечивает автоматическое преобразование пользовательских типов в классы PHP.

Технология SOAP также является идеальным примером того, что простая идея не всегда означает простую реализацию. SOAP сообщение состоит из конверта, содержащего заголовок и тело. Имена всех элементов в SOAP-документе определены, что хотя и повышает надежность, но затрудняет восприятие получившегося XML-документа человеком. На верхнем уровне иерархии находится конверт (envelope), представляющий собой контейнер для SOAP-сообщения. Он располагается в пространстве имен xmlsoap, что, как правило, указывается в его полном имени и последующем объявлении пространства имен.

SOAP неявно использует язык XML-схемы (XML Schema), представляющий собой язык для определения и проверки структур данных на основе XML. Согласно стандарту пространство имен для элементов XML-документа описывается в отдельном файле, содержащим XML-схему и также являющимся XML-документом.

СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ

  1. Стандарт SOAP - http://www.w3.org/TR/soap/
  2. Спецификация XML, http://www.w3.org/TR/xml
  3. Спецификация WSDL версия 1.1, http://www.w3.org/TR/wsdl
  4. Спецификация WSDL версия 2.0, http://www.w3.org/TR/wsdl20
  5. Спецификация UDDI версия 3, http://uddi.org/pubs/uddi_v3.htm
  6. SOAP Версия 1.2 Часть 0: Учебник для начинающих : http://www.w3.org/2002/07/soaptranslation/russian/part0.html
  7. Хабибуллин И.Ш. Разработка Web-служб средствами Java. — СПб. : БХВ-Петербург, 2015. — 400 с: ил.
  8. Технологии и средства консолидации информации: Учебное пособие. Деревянко А.С., Солощук М.Н. - Харьков: НТУ "ХПИ", 2013. - 432c.
  9. Arulazi Dhesiaseelan, “What's new in WSDL 2.0”, http://www.xml.com/pub/a/ws/2004/05/19/wsdl2.html
  10. Apache Axis2, http://ws.apache.org/axis2
  11. S. W. Eran Chinthaka, “Axis2: The Next Generation of Apache Web Services”, http://today.java.net/pub/a/today/2006/09/07/axis2-next-generation-web-services.html
  12. Ajith Ranabahu, “Inside the Axis2 Code Generator”, http://wso2.org/node/35
  13. WSDL4R, http://dev.ctor.org/soap4r
  14. NET Web Service Description Language Tool, http://msdn2.microsoft.com/enus/library/7h3ystb6(VS.80).aspx
  15. wsdl2js (Java), http://sourceforge.net/projects/wsdl2js