Введение
Общая идея служб выражается в следующем примере. Представим есть пользователь, он заходит на сайт, который сделали мы. На нашем сайте есть возможность посмотреть расписание рейсов автобусов из городов Украины в Европейские города. Но при этом наш сайт не располагает базой данных, в которой описаны все рейсы. Эти данные есть в гос. службе автовокзала.
Так вот, на сервере автовокзала, программисты пишут веб сервис, а мы на своем сайте пишем сервис клиент. И далее процесс идет таким путем:
- пользователь делает запрос указывая при этом интересующие данные,
- мы формируем полученные от пользователя данные и отправляем их запросом на веб сервис автовокзала,
- там этот запрос обрабатывается сервисом, и нам летят данные из их базы данных,
- мы отображаем эти данные на нашем сайте пользователю.
Для дополнительной наглядности рисунок 1.

Рисунок №1 — Общая идея работы веб службы
Характерными особенностями веб служб является:
- использование протокола http для доступа к сервису,
- если это, например, xml сервис, то данные между клиентом и сервером передаются именно в формате xml,
- независимость от языка программирования.
История появления веб-служб берет свое начало с появления такого подхода, как Remote Procedure Call (RPC) или вызов удаленных процедур. Этот подход позволяет программе вызывать процедуры из удаленного адресного пространства.
Важно!
Remote Procedure Call — это именно подход, идея. Не путать с конкретной реализацией. Например, есть идея игры в мяч. Суть которой, что есть две команды ,которые пытаются забросить друг другу мяч. И та команда, которая больше забросит, побеждает. Это идея, а вот, например, футбол — это конкретная реализация.
Идея RPC получила ряд реализаций:
- XML-RPC,
- SOAP,
- JSON-RPC,
- .NET Remoting,
- DCOM,
- JAVA RMI.
Simple Object Access Protocol
SOAP — это простой протокол доступа к объектам. Запросы посылаются по протоколу http и методом POST. Между клиентом и сервером передается xml строка. Передаваемый xml состоит из трех главных элементов:
- Envelope,
- Header,
- Body.
Пример SOAP запроса
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <getStock xmlns="http://site.ru/ws"> <num>12345</num> </getStock> </soap:Body> </soap:Envelope> Тут происходит следующее. Запрос вызывает процедуру под именем getStock и передает ей параметр 12345. Ответ от сервера может иметь, например, такой вид <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <getStockDetailsResponse xmlns="http://site.ru/ws"> <getStockDetailsResult> <id>12345</id> <productName>Стакан граненый</productName> <description>Стакан граненый. 250 мл.</description> <price>9.95</price> </getStockDetailsResult> </getStockDetailsResponse> </soap:Body> </soap:Envelope>
В php для этих целей есть модуль php_soap.dll. Который предоставляет два класса для работы. Это:
- SoapServer,
- SoapClient.
Первый пример из урока (SOAP), представлен тремя файлами — client, service и wsdl.
<!-- client--> //Создание SOAP-клиента //Параметром передаем адрес wsdl. //После чего, все операции, перечисленные в этом документе //становятся методами объекта $client = new SoapClient("http://pb.seolab.dp.ua/soap/stock.wsdl"); //Отправка запроса и получение результата $res = $client->getStock(2); echo "$res"; <!-- service --> //Описание функции Web-сервиса function getStock($id){ $stock = array( "1" => 100, "2" => 200, "3" => 300, "4" => 400, "5" => 500, ); if(isset($stock[$id])){ return $stock[$id]; }else{ return 0; } } //Создаем SOAP-сервер //И в конструктор передаем адрес, по которому расположен //файл wsdl с описанием службы $server = new SoapServer("https://pb.seolab.dp.ua/soap/stock.wsdl"); //Регистрируем функцию, к которой будет обращаться клиент $server->addFunction("getStock"); //Запускаем сервер $server->handle(); <!-- WSDL --> <?xml version="1.0" encoding="UTF-8"?> <!-- Web Services Description Language (WSDL) Это xml документ, используемый для описания веб службы. Описывает: - Где находится служба - Какие функции доступны клиенту - Количество аргументов функций - Типы аргументов функций - Типы возвращаемых функциями значений - Описание пользовательских типов для параметров функций--> <definitions name='News' targetNamespace='http://pb.seolab.dp.ua/soap' xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/' xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/' xmlns='http://schemas.xmlsoap.org/wsdl/'> <message name='getStockRequest'> <!-- входящий параметр с типом integer --> <part name='id' type='xsd:integer' /> </message> <message name='getStockResponse'> <!-- возвращаемый параметр с типом integer --> <part name='item' type='xsd:integer' /> </message> <portType name='StockPortType'> <operation name='getStock'><!-- наличие элементов input и output говорит о том, что функция и принимает и возвращает --> <input message='tns:getStockRequest' /><!-- в атрибуте message указано имя элемента, где описаны типы данных, которые принимает функция --> <output message='tns:getStockResponse' /><!-- в атрибуте message указано имя элемента, где описаны типы данных, которые возвращает функция --> </operation> </portType> <binding name='StockBinding' type='tns:StockPortType'><!-- Список доступных функций и имя элемента, в котором описан тип доступных функций (т.е. фун-ция только принимает или принимает и возвращает), указано в атрибуте "type"--> <soap:binding style='rpc' transport='http://schemas.xmlsoap.org/soap/http' /> <operation name='getStock' /><!-- Имя доступной функции. Количество элементов "operation" = кол-ву доступных для клиента функций --> </binding> <service name='StockService'><!-- имя сервиса --> <port name='StockPort' binding='StockBinding'><!-- тут указывается имя элемента, в котором описаны доступные функции --> <soap:address location='https://pb.seolab.dp.ua/soap/service.php' /><!-- указание адреса службы --> </port> </service> </definitions>
Нюансы в работе с SOAP
- При регистрации доступной для клиента функции ($server->addFunction(«getStock»)), в нашем примере используется лишь одна функция. Если необходимо указать список доступных функций нужно создать массив с именами доступных функций. $func = [«getStock», «setStock»]; и передать уже имя массива $server->addFunction(«$func»).
- Для того, чтобы на стороне клиента получить описание доступной нам функции используется метод __getFunctions. В представленном выше примере, это имело бы следующий вид — print_r($client->__getFunctions());//Array ([0] => integer getStock(integer $id))
Автор Виталий Сухомлинов
практикующий веб разработчик
и seo-специалист