PHP программирование → Пишем веб-сервис с использованием протокола SOAP
В главных ролях:
— фреймворк CodeIgniter
— протокол SOAP
— методы getCategories() и getVideos($params = array()) — придуманы для примера
— сайт www.videobox.su используется просто, как заглушка, просто не хотел писать yourdomain.com
У нас есть ресурс с определенными данными, например, это будет видео ресурс. Мы хотим дать возможность другим ресурсам тянуть данные с нашего сайта. Было бы хорошо дать возможность сторонним программистам вызывать наши методы. Именно с вызовом удаленных процедур нам поможет SOAP.
Структура сей системы:
— Клиент
— Сервер
Мы хотим отдать на доступ два метода getCategories(), который будет возвращать список всех категорий нашего сайта и getVideos($params = array()) — он будет отдавать список видео с информацией в зависимости от входящих параметров $params.
Для начала нам необходимо создать WSDL документ, который опишет два наших метода (имеа методов, входящие данные и возвращаемые данные), по сути это файл в обычном XML формате.
Назовем наш файл webservice.wsdl и положим его по адресу http://videobox.su/webservice/webservice.wsdl
Создадим контроллер, который и будет являться нашим сервером.
Наш сервер готов и доступен по адресу http://videobox.su/webservice/.
Клиент это та, часть, которая создается сторонними разработчиками с использованием методов, которые мы отдали для использования.
Опять же, создаем контроллер Webserviceclient (если клиент использует CodeIgniter) или не создаем, а а просто используем код, который описан в методе контроллера index(). В любом случае он будет доступен там, где вы его создали.
В результате мы получим вывод двух массивов данных или в чем придумаете выдачу данных в своей реализации.
Статья была написана в качестве примера, т.к. в интернете не было найдено ничего толкового, а именно были описаны абстрактные примеры, которые трудно соединить в систему, так же сложно было найти, как передать массив в качестве параметра:)
— фреймворк CodeIgniter
— протокол SOAP
— методы getCategories() и getVideos($params = array()) — придуманы для примера
— сайт www.videobox.su используется просто, как заглушка, просто не хотел писать yourdomain.com
Для чего нам нужен SOAP
У нас есть ресурс с определенными данными, например, это будет видео ресурс. Мы хотим дать возможность другим ресурсам тянуть данные с нашего сайта. Было бы хорошо дать возможность сторонним программистам вызывать наши методы. Именно с вызовом удаленных процедур нам поможет SOAP.
Структура сей системы:
— Клиент
— Сервер
Пишем сервер
Мы хотим отдать на доступ два метода getCategories(), который будет возвращать список всех категорий нашего сайта и getVideos($params = array()) — он будет отдавать список видео с информацией в зависимости от входящих параметров $params.
Для начала нам необходимо создать WSDL документ, который опишет два наших метода (имеа методов, входящие данные и возвращаемые данные), по сути это файл в обычном XML формате.
Назовем наш файл webservice.wsdl и положим его по адресу http://videobox.su/webservice/webservice.wsdl
<?xml version ='1.0' encoding ='UTF-8' ?>
<definitions name='webservice'
targetNamespace='uri:webservice'
xmlns:tns='uro:webservice'
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/'>
<types>
<!-- описываем тип данных ArrayOfParams, т.к. просто входящим параметром данные типа Array SOAP принимать не умеет -->
<schema targetNamespace="http://example.com/stockquote/schema" xmlns="http://www.w3.org/2000/10/XMLSchema">
<complexType name="ArrayOfParams">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
</restriction>
</complexContent>
</complexType>
</schema>
</types>
<message name='getVideosRequest'>
<part name='params' type='xsd:ArrayOfParams'/>
</message>
<message name='getVideosResponse'>
<part name='Result' type='xsd:Array'/>
</message>
<!-- т.к. входящих параметров для метода getCategories() нет, мы не описываем Request -->
<message name='getCategoriesResponse'>
<part name='Result' type='xsd:Array'/>
</message>
<portType name='webservicePortType'>
<operation name='getVideos'>
<input message='tns:getVideosRequest'/>
<output message='tns:getVideosResponse'/>
</operation>
<operation name='getCategories'>
<input message='tns:getCategoriesRequest'/>
<output message='tns:getCategoriesResponse'/>
</operation>
</portType>
<binding name='webserviceBinding' type='tns:webservicePortType'>
<soap:binding style='rpc' transport='http://schemas.xmlsoap.org/soap/http'/>
<operation name='getVideos'>
<soap:operation soapAction='urn:webservice-video#getVideos'/>
<input>
<soap:body use='encoded' namespace='urn:webservice-video' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</input>
<output>
<soap:body use='encoded' namespace='urn:webservice-video' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</output>
</operation>
<operation name='getCategories'>
<soap:operation soapAction='urn:webservice-video#getCategories'/>
<input>
<soap:body use='encoded' namespace='urn:webservice-video' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</input>
<output>
<soap:body use='encoded' namespace='urn:webservice-video' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</output>
</operation>
</binding>
<service name='webserviceService'>
<port name='webservicePort' binding='webserviceBinding'>
<!-- URL к нашему серверу -->
<soap:address location='http://videobox.su/webservice/'/>
</port>
</service>
</definitions>
<definitions name='webservice'
targetNamespace='uri:webservice'
xmlns:tns='uro:webservice'
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/'>
<types>
<!-- описываем тип данных ArrayOfParams, т.к. просто входящим параметром данные типа Array SOAP принимать не умеет -->
<schema targetNamespace="http://example.com/stockquote/schema" xmlns="http://www.w3.org/2000/10/XMLSchema">
<complexType name="ArrayOfParams">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
</restriction>
</complexContent>
</complexType>
</schema>
</types>
<message name='getVideosRequest'>
<part name='params' type='xsd:ArrayOfParams'/>
</message>
<message name='getVideosResponse'>
<part name='Result' type='xsd:Array'/>
</message>
<!-- т.к. входящих параметров для метода getCategories() нет, мы не описываем Request -->
<message name='getCategoriesResponse'>
<part name='Result' type='xsd:Array'/>
</message>
<portType name='webservicePortType'>
<operation name='getVideos'>
<input message='tns:getVideosRequest'/>
<output message='tns:getVideosResponse'/>
</operation>
<operation name='getCategories'>
<input message='tns:getCategoriesRequest'/>
<output message='tns:getCategoriesResponse'/>
</operation>
</portType>
<binding name='webserviceBinding' type='tns:webservicePortType'>
<soap:binding style='rpc' transport='http://schemas.xmlsoap.org/soap/http'/>
<operation name='getVideos'>
<soap:operation soapAction='urn:webservice-video#getVideos'/>
<input>
<soap:body use='encoded' namespace='urn:webservice-video' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</input>
<output>
<soap:body use='encoded' namespace='urn:webservice-video' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</output>
</operation>
<operation name='getCategories'>
<soap:operation soapAction='urn:webservice-video#getCategories'/>
<input>
<soap:body use='encoded' namespace='urn:webservice-video' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</input>
<output>
<soap:body use='encoded' namespace='urn:webservice-video' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</output>
</operation>
</binding>
<service name='webserviceService'>
<port name='webservicePort' binding='webserviceBinding'>
<!-- URL к нашему серверу -->
<soap:address location='http://videobox.su/webservice/'/>
</port>
</service>
</definitions>
Создадим контроллер, который и будет являться нашим сервером.
<?
class Webservice extends Controller{
function __construct(){
parent::Controller();
$this->load->model("video");
$this->load->model("category");
}
function index(){
function getVideos($params) {
$CI = &get_instance ();
$videos = array();
//проверка входящих данных
if(!is_array($params) || sizeof($params) == 0) {
throw new SoapFault("Server:", '$params' . " has wrong format. Can be Array();");
}
else {
return $CI->video->getVideo($params); // выборка данных по видео, здесь можно описать свой код, для краткости сделан вызов из модели
}
}
function getCategories() {
return $CI->category->getAll(); // выборка данных по категориям, здесь можно описать свой код, для краткости сделан вызов из модели
}
ini_set("soap.wsdl_cache_enabled", "0"); // отключение кеширования wsdl файла
$server = new SoapServer("http://videobox.su/webservice/webservice.wsdl?" . rand()); // случайное число добавляем для дебага, т.к. wsdl файл сразуже кешируется и не всегда есть доступ к php.ini или к функции ini_set для отключения кеширования на кремя дебага
$server->addFunction("getVideos");
$server->addFunction("getCategories");
$server->handle();
}
?>
class Webservice extends Controller{
function __construct(){
parent::Controller();
$this->load->model("video");
$this->load->model("category");
}
function index(){
function getVideos($params) {
$CI = &get_instance ();
$videos = array();
//проверка входящих данных
if(!is_array($params) || sizeof($params) == 0) {
throw new SoapFault("Server:", '$params' . " has wrong format. Can be Array();");
}
else {
return $CI->video->getVideo($params); // выборка данных по видео, здесь можно описать свой код, для краткости сделан вызов из модели
}
}
function getCategories() {
return $CI->category->getAll(); // выборка данных по категориям, здесь можно описать свой код, для краткости сделан вызов из модели
}
ini_set("soap.wsdl_cache_enabled", "0"); // отключение кеширования wsdl файла
$server = new SoapServer("http://videobox.su/webservice/webservice.wsdl?" . rand()); // случайное число добавляем для дебага, т.к. wsdl файл сразуже кешируется и не всегда есть доступ к php.ini или к функции ini_set для отключения кеширования на кремя дебага
$server->addFunction("getVideos");
$server->addFunction("getCategories");
$server->handle();
}
?>
Наш сервер готов и доступен по адресу http://videobox.su/webservice/.
Пишем клиент
Клиент это та, часть, которая создается сторонними разработчиками с использованием методов, которые мы отдали для использования.
Опять же, создаем контроллер Webserviceclient (если клиент использует CodeIgniter) или не создаем, а а просто используем код, который описан в методе контроллера index(). В любом случае он будет доступен там, где вы его создали.
<?
class Webserviceclient extends Controller{
function __construct(){
parent::Controller();
}
function index(){
try {
$client = new SoapClient("http://videobox.su/webservice/webservice.wsdl?" . rand(),
array(
"trace" => 1,
"exceptions" => 0
)
);//второй параметр необходим для отладки, является не обязательным
$params = array(
"vid" => 64, //выбираем видео с ID = 64
);
print "<pre>";
print_r($client->getVideos($params)); // вызов метода сервера на выборку данных по видео
//print "Request :\n".htmlspecialchars($client->__getLastRequest()) ."\n
"; // показать запрос к серверу (работает при включенном дебаге), кому интересно посмотреть на XML - раскомментировать
//print "Answer:\n".htmlspecialchars($client->__getLastResponse())."\n
"; // показать ответ сервера (работает при включенном дебаге), кому интересно посмотреть на XML - раскомментировать
print_r($client->getCategories()); // вызов метода сервера на выборку доступных категорий
//print "Request :\n".htmlspecialchars($client->__getLastRequest()) ."\n
";
//print "Answer:\n".htmlspecialchars($client->__getLastResponse())."\n
";
print "</pre>";
}
catch (Exception $e){
print $e;
echo 'Error Caught';
}
}
}
?>
class Webserviceclient extends Controller{
function __construct(){
parent::Controller();
}
function index(){
try {
$client = new SoapClient("http://videobox.su/webservice/webservice.wsdl?" . rand(),
array(
"trace" => 1,
"exceptions" => 0
)
);//второй параметр необходим для отладки, является не обязательным
$params = array(
"vid" => 64, //выбираем видео с ID = 64
);
print "<pre>";
print_r($client->getVideos($params)); // вызов метода сервера на выборку данных по видео
//print "Request :\n".htmlspecialchars($client->__getLastRequest()) ."\n
"; // показать запрос к серверу (работает при включенном дебаге), кому интересно посмотреть на XML - раскомментировать
//print "Answer:\n".htmlspecialchars($client->__getLastResponse())."\n
"; // показать ответ сервера (работает при включенном дебаге), кому интересно посмотреть на XML - раскомментировать
print_r($client->getCategories()); // вызов метода сервера на выборку доступных категорий
//print "Request :\n".htmlspecialchars($client->__getLastRequest()) ."\n
";
//print "Answer:\n".htmlspecialchars($client->__getLastResponse())."\n
";
print "</pre>";
}
catch (Exception $e){
print $e;
echo 'Error Caught';
}
}
}
?>
В результате мы получим вывод двух массивов данных или в чем придумаете выдачу данных в своей реализации.
Статья была написана в качестве примера, т.к. в интернете не было найдено ничего толкового, а именно были описаны абстрактные примеры, которые трудно соединить в систему, так же сложно было найти, как передать массив в качестве параметра:)



