---
title: "SOAP сервер на Zend Framework с использованием Zend_Soap_AutoDiscover для работы с клиентом написаным на .NET"
description: "При работе над одним порталом у нас возникла задача, по обмену данными между порталом и несколькими ..."
author: "alexboo"
published: "2012-08-25T23:41:22+00:00"
modified: "2012-08-26T00:06:26+00:00"
locale: "ru"
canonical_url: "https://yvision.kz/post/soap-server-na-zend-framework-s-ispolzovaniem-zend-soap-autodiscover-dlya-raboty-s-klientom-napisany-88433"
markdown_url: "https://yvision.kz/post/soap-server-na-zend-framework-s-ispolzovaniem-zend-soap-autodiscover-dlya-raboty-s-klientom-napisany-88433/markdown"
site_name: "Yvision.kz"
---

# SOAP сервер на Zend Framework с использованием Zend_Soap_AutoDiscover для работы с клиентом написаным на .NET

> При работе над одним порталом у нас возникла задача, по обмену данными между порталом и несколькими ...

При работе над одним порталом у нас возникла задача, по обмену данными между порталом и несколькими другими программами написанными на .NET. Разработчики этих программ настаивали сделать взаимодействие при помощи SOAP, мы согласились.

В этой статье хотелось бы раскрыть проблемы возникшие при разработке SOAP сервера на Zend Framework с использованием Zend_Soap_AutoDiscover.

Так как портал был полностью реализован на Zend Framework мы и решили реализовать SOAP сервер на нем. Так же мы решили использовать AutoDiscover что бы не писать wsdl файл в ручную, так как планировалось что в наш сервер будет добавляться различный функционал в будущем. И не хотелось тратить время на описание этих функций в wsdl файле. Заглянув в ман мы нашли код нужный для создания SOAP сервера.

- if([isset](http://www.php.net/isset)($_GET['wsdl'])) {

- $autodiscover = new Zend_Soap_AutoDiscover();

- $autodiscover->setClass('ExcampleService');

- $autodiscover->handle();

- } else {

- // pointing to the current file here

- $soap = new Zend_Soap_Server("http://example.com/soap.php?wsdl");

- $soap->setClass('ExcampleService');

- $soap->handle();

- }

Как же все просто подумали мы, но .NET отказался работать с нашим сервером. Мы стали искать проблемы почему не работает наш сервер с .NET программами, когда клиент на PHP успешно обменивался данными с ним.

**Проблема первая.**

Как мы знаем PHP не типизированный язык, когда .NET типизированный и это первая проблема. Потому что при генерации wsdl AutoDiscover не может определить типы возвращаемых данных. Для решения этой проблемы нужно указывать тип возвращаемых данных в описании функций.

***Пример описания:***

- class ExcampleService {

- /**

- * Return true if record active, else if record inactive

- *

- * @param integer $recordId

- * @return boolean

- */

- public function isActiveRecord($recordId) {

- $recordsTable = new Model_Records();
- return $recordsTable->isActiveRecord($recordId);

- }

- }

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

***Пример описания классов возвращаемых объектов:***

 

- class SRecord {

- /** @var int */

- public $id;

- /** @var string */

- public $text;

- }

- class SRecordsArray {

- /** @var SRecord[] */

- public $records;

- }

***И код самого класса ExcampleService:***

*** ***

- class ExcampleService {

- /**

- * Return true if record active, else if record inactive

- *

- * @param integer $recordId

- * @return boolean

- */

- public function isActiveRecord($recordId) {

- $recordsTable = new Model_Records();
- return $recordsTable->isActiveRecord($recordId);

- }

- /**

- * Return list of records

- *

- * @return SRecordsArray

- */

- public function getList() {

- $recordsTable = new Model_Records();

- $records = $recordsTable -> getList();

- $result = [array](http://www.php.net/array)();
- foreach ($records as $record) {

- $oSrecord = new SRecord();

- $oSrecord->id = $record->id;

- $oSrecord->text = $record->text;

- $result[] = $oSrecord;

- }

- $oSrecordsArray = new SRecordsArray();

- $oSrecordsArray->records = $result;
- return $oSrecordsArray;

- }

- }

 

Сохраняем изменения запускаем программу .NET и видим что она снова отказывается работать.

**Проблема вторая.**

Проблема в том что .NET поддерживает только один стандарт SOAP WS-I а AutoDiscover по умолчанию использует стандарт XSD поэтому нам нужно привести wsdl к стандарту WS-I. Для этого нам нужно доработать первоначальный код следующим образом.

- if([isset](http://www.php.net/isset)($_GET['wsdl'])) {

- $autodiscover = new Zend_Soap_AutoDiscover('Zend_Soap_Wsdl_Strategy_ArrayOfTypeSequence');

- $autodiscover->setBindingStyle([array](http://www.php.net/array)('style'=>'document'));

- $autodiscover->setOperationBodyStyle([array](http://www.php.net/array)('use' => 'literal'));

- $autodiscover->setClass('ExcampleService');

- $autodiscover->handle();

- } else {

- // pointing to the current file here

- $soap = new Zend_Soap_Server("http://example.com/soap.php?wsdl");

- $soap->setClass('ExcampleService');

- $soap->handle();

- }

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

**Проблема третья.**

Последняя проблема связанна с получением и передачей данных. Для решения этой проблемы мы написали специальный класс который трансформирует входящие и исходящие данные.

***Исходный код класса:***

- class Service_Soap

- {

- protected $_service;
- public function __construct()

- {

- $this->_service = new ExcampleService();

- }

- public function __call($name, $arguments)

- {

- $params = [array](http://www.php.net/array)();
- if([count](http://www.php.net/count)($arguments) > 0){

- foreach($arguments[0] as $property=>$value){

- $params[$property] = $value;

- }

- }

- $result = [call_user_func_array](http://www.php.net/call_user_func_array)([array](http://www.php.net/array)($this->_service, $name), $params);
- return [array](http://www.php.net/array)("{$name}Result" => $result);

- }

- }

 

***И доработали код создания сервера***

 

- if([isset](http://www.php.net/isset)($_GET['wsdl'])) {

- $autodiscover = new Zend_Soap_AutoDiscover('Zend_Soap_Wsdl_Strategy_ArrayOfTypeSequence');

- $autodiscover->setBindingStyle([array](http://www.php.net/array)('style'=>'document'));

- $autodiscover->setOperationBodyStyle([array](http://www.php.net/array)('use' => 'literal'));

- $autodiscover->setClass('ExcampleService');

- $autodiscover->handle();

- } else {

- // pointing to the current file here

- $soap = new Zend_Soap_Server("http://example.com/soap.php?wsdl");

- //$soap->setClass('ExcampleService');

- $modelSoap = new Service_Soap();

- $soap->setObject($modelSoap);

- $soap->handle();

- }

 

После сохранения программа на .NET заработала и портал стал обмениваться данными с ней.

Надеюсь что этот пост поможет кому то при разработке SOAP сервера. И он уже быстро справится с проблемами описанными в статье, нам решение этих проблем заняло достаточно времени.

Спасибо всем за внимание и удачи вам!

---

Source: [https://yvision.kz/post/soap-server-na-zend-framework-s-ispolzovaniem-zend-soap-autodiscover-dlya-raboty-s-klientom-napisany-88433](https://yvision.kz/post/soap-server-na-zend-framework-s-ispolzovaniem-zend-soap-autodiscover-dlya-raboty-s-klientom-napisany-88433)