我正在尝试实现一个Soap服务器,我正在尝试查看Zend Framework(1)中的Soap服务器是否能满足我的需求。我有兴趣尝试利用它的自动发现来创建WSDL,所以我不需要在任何时候对函数或数据类型进行单独维护。
我设置了一个基本服务器,我能够进行自动发现,看似按照自己的意愿行事,并在客户端中使用类映射进行播放,并且能够从返回的数据中正确填充模型一些复杂的数据类型。但是,我似乎无法弄清楚如何向客户端传递一个对象并让它在远端正确显示。
当我最初传入一个值数组(嵌套/关联)时,客户端在'output'类型/模型/对象中生成了所需的结果。但是当我试图将对象传递给客户端代码时,它在服务器上显示为一个值数组(而不是关联的 - 键被丢弃。在另一个测试中,我尝试嵌套对象,第二个对象显示为stdClass但至少具有预期的键/值,但外部的一个始终是顺序数组)
看来autoDiscover至少假装它已经准备好做我想要的了,但我不知道如何从发送到客户端的对象中获取数据以便在服务器上正确显示。
服务器代码收到的数据:
array (
0 => 4,
1 => 12,
2 => 7,
3 => 98.6,
4 => 9.18,
5 => 3.1415,
6 => 'foobar',
7 => 'change',
8 => 'bumblebee',
)
输入类:
class InputType {
/**
* @var integer $intOne
*/
public $intOne;
/**
* @var integer $intTwo
*/
public $intTwo;
/**
* @var integer $intThree
*/
public $intThree;
/**
* @var float $floatOne
*/
public $floatOne;
/**
* @var float $floatTwo
*/
public $floatTwo;
/**
* @var float $floatThree
*/
public $floatThree;
/**
* @var string $stringOne
*/
public $stringOne;
/**
* @var string $stringOne
*/
public $stringTwo;
/**
* @var string $stringThree
*/
public $stringThree;
}
示例复杂对象(输出父图层)
require_once('SOAP/Types/TestClassType.php');
class TestType {
/**
* @var integer $intVar
*/
public $intVar;
/**
* @var float $floatVar
*/
public $floatVar;
/**
* @var string $stringVar
*/
public $stringVar;
/**
* @var array $arrayVar
*/
public $arrayVar;
/**
* @var TestClassType $classVar
*/
public $classVar;
public function __construct() {
$this->classVar = new TestClassType();
}
}
测试类模型(输出子)
class TestClassType {
/**
* @var integer $testInt
*/
public $testInt;
/**
* @var float $testFloat
*/
public $testFloat;
/**
* @var string $testString
*/
public $testString;
}
服务器代码(功能):
require_once('SOAP/Types/InputType.php');
require_once('SOAP/Types/TestType.php');
require_once('SOAP/Types/TestClassType.php');
class Soap_Server {
/**
* get a complex type
*
* @param InputType $inp
* @return TestType
*/
public function get_test_type($inp) {
error_log("Input: " . var_export($inp,1));
$tt = new TestType();
$tt->intVar = $inp->intOne;
$tt->floatVar = $inp->floatOne;
$tt->stringVar = $inp->stringOne;
$tt->arrayVar = array(
'int' => $inp->intThree,
'float' => $inp->floatThree,
'string' => $inp->stringThree
);
$tt->classVar->testInt = $inp->intTwo;
$tt->classVar->testFloat = $inp->floatTwo;
$tt->classVar->testString = $inp->stringTwo;
return $tt;
}
}
服务器请求处理程序(在apache2上运行):
require_once('SOAP/Types/InputType.php');
require_once('SOAP/Types/TestType.php');
require_once('SOAP/Types/TestClassType.php');
require_once('SOAP/Server.php');
if(isset($_GET['wsdl'])) {
//return the WSDL
handleWSDL();
} else {
//handle SOAP request
handleSOAP();
}
exit();
function handleWSDL() {
require_once('Zend/Soap/AutoDiscover.php');
$autodiscover = new Zend_Soap_AutoDiscover();
$autodiscover->setClass('Soap_Server');
ob_clean();
ob_start();
$autodiscover->handle();
}
function handleSOAP() {
$wsdl = "http://localhost/soap/zendserver.php?wsdl";
require_once('Zend/Soap/Server.php');
$server = new Zend_Soap_Server($wsdl);
$server->setClass('Soap_Server');
$server->setClassmap(
array(
'InputType' => 'InputType',
'TestType' => 'TestType',
'TestClassType' => 'TestClassType'
)
);
$server->handle();
}
测试客户端代码:
require_once('SOAP/Types/InputType.php');
require_once('SOAP/Types/TestType.php');
require_once('SOAP/Types/TestClassType.php');
require_once('Zend/Soap/Client.php');
$wsdl = "http://localhost/soap/zendserver.php?wsdl";
$client = new Zend_Soap_Client($wsdl, array('cache_wsdl' => false ));
$client->setClassmap(
array(
'InputType' => 'InputType',
'TestType' => 'TestType',
'TestClassType' => 'TestClassType'
)
);
$client->setWsdlCache(false);
$bar = new InputType();
$bar->intOne = 4;
$bar->floatOne = 98.6;
$bar->stringOne = "foobar";
$bar->intTwo = 12;
$bar->floatTwo = 9.18;
$bar->stringTwo = "change";
$bar->intThree = 7;
$bar->floatThree = 3.1415;
$bar->stringThree = "bumblebee";
$result = $client->get_test_type($bar);
autoDiscover WSDL:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://localhost/soap/zendserver.php" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" name="Soap_Server" targetNamespace="http://localhost/soap/zendserver.php">
<types>
<xsd:schema targetNamespace="http://localhost/soap/zendserver.php">
<xsd:complexType name="InputType">
<xsd:all>
<xsd:element name="intOne" type="xsd:int" nillable="true"/>
<xsd:element name="intTwo" type="xsd:int" nillable="true"/>
<xsd:element name="intThree" type="xsd:int" nillable="true"/>
<xsd:element name="floatOne" type="xsd:float" nillable="true"/>
<xsd:element name="floatTwo" type="xsd:float" nillable="true"/>
<xsd:element name="floatThree" type="xsd:float" nillable="true"/>
<xsd:element name="stringOne" type="xsd:string" nillable="true"/>
<xsd:element name="stringTwo" type="xsd:string" nillable="true"/>
<xsd:element name="stringThree" type="xsd:string" nillable="true"/>
</xsd:all>
</xsd:complexType>
<xsd:complexType name="TestClassType">
<xsd:all>
<xsd:element name="testInt" type="xsd:int" nillable="true"/>
<xsd:element name="testFloat" type="xsd:float" nillable="true"/>
<xsd:element name="testString" type="xsd:string" nillable="true"/>
</xsd:all>
</xsd:complexType>
<xsd:complexType name="TestType">
<xsd:all>
<xsd:element name="intVar" type="xsd:int" nillable="true"/>
<xsd:element name="floatVar" type="xsd:float" nillable="true"/>
<xsd:element name="stringVar" type="xsd:string" nillable="true"/>
<xsd:element name="arrayVar" type="soap-enc:Array" nillable="true"/>
<xsd:element name="classVar" type="tns:TestClassType" nillable="true"/>
</xsd:all>
</xsd:complexType>
</xsd:schema>
</types>
<portType name="Soap_ServerPort">
<operation name="get_test_type">
<documentation>get a complex type</documentation>
<input message="tns:get_test_typeIn"/>
<output message="tns:get_test_typeOut"/>
</operation>
</portType>
<binding name="Soap_ServerBinding" type="tns:Soap_ServerPort">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="get_test_type">
<soap:operation soapAction="http://localhost/soap/zendserver.php#get_test_type"/>
<input>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://www.localhost.com/soap/zendserver.php"/>
</input>
<output>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/soap/zendserver.php"/>
</output>
</operation>
</binding>
<service name="Soap_ServerService">
<port name="Soap_ServerPort" binding="tns:Soap_ServerBinding">
<soap:address location="http://localhost/soap/zendserver.php"/>
</port>
</service>
<message name="get_test_typeIn">
<part name="inp" type="tns:InputType"/>
</message>
<message name="get_test_typeOut">
<part name="return" type="tns:TestType"/>
</message>
</definitions>