从NuSoap到php Soap,真是付出了惨痛的代价。
php Soap对于complex 参数类型的封装,采用array来实现,array扮演了class的角色;
如果在WSDL文件中定义了以下complex参数
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="XXXX" targetNamespace="http://www.example.com"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.example.com"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<xsd:schema targetNamespace="http://www.example.com">
<xsd:complexType name="BusinessErrorType">
<xsd:sequence>
<xsd:element name="severityCode" type="xsd:string" minOccurs="0">
</xsd:element>
<xsd:element name="reasonCode" type="xsd:string" minOccurs="0">
</xsd:element>
<xsd:element name="reasonText" type="xsd:string" minOccurs="0">
</xsd:element>
<xsd:element name="reasonDetail" type="xsd:string" minOccurs="0">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="AddAccessCardDetails" type="tns:AccessCardRequestType">
</xsd:element>
<xsd:element name="AddAccessCardDetailsResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="messageId" type="xsd:string">
</xsd:element>
<xsd:element name="resultCondition" type="tns:BusinessErrorType" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="AccessCardRequestType">
<xsd:sequence>
<xsd:element name="messageId" type="xsd:string"></xsd:element>
<xsd:element maxOccurs="unbounded" minOccurs="1" name="cardInfo" type="tns:CardLocationAccessInfoType">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CardLocationAccessInfoType">
<xsd:sequence>
<xsd:element minOccurs="0" name="residentID" type="xsd:string">
</xsd:element>
<xsd:element name="cardUID" type="tns:CardUIDType">
</xsd:element>
<xsd:element name="accessExpiryDate" type="xsd:string">
</xsd:element>
<xsd:element minOccurs="0" name="locationAccess" type="tns:LocationAccessType" maxOccurs="unbounded">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="LocationAccessType">
<xsd:sequence>
<xsd:element name="accessPermission">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="ALLOW"></xsd:enumeration>
<xsd:enumeration value="BLOCK"></xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="project" type="xsd:string">
</xsd:element>
<xsd:element name="building" type="xsd:string">
</xsd:element>
<xsd:element minOccurs="0" name="wing"
type="xsd:string" />
<xsd:element name="door" type="xsd:string"></xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CardUIDType">
<xsd:sequence>
<xsd:element name="ARN" type="xsd:string"></xsd:element>
<xsd:element name="expiryDate" type="xsd:string"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="AddAccessCardDetailsRequest">
<wsdl:part element="tns:AddAccessCardDetails" name="parameters"/>
</wsdl:message>
<wsdl:message name="AddAccessCardDetailsResponse">
<wsdl:part element="tns:AddAccessCardDetailsResponse" name="parameters"/>
</wsdl:message>
<wsdl:portType name="XPServices">
<wsdl:operation name="AddAccessCardDetails">
<wsdl:input message="tns:AddAccessCardDetailsRequest"/>
<wsdl:output message="tns:AddAccessCardDetailsResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="XServicesSOAP"
type="tns:XPServices">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="AddAccessCardDetails">
<soap:operation
soapAction="AddAccessCardDetails" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="XServices">
<wsdl:port name="XServicesSOAP" binding="tns:XServicesSOAP">
<soap:address location='http://www.example.com/Xservice.php'/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
则在调用接口AddAccessCardDetails时应该这样传参:
<?php
$client = new SoapClient("http://www.example.com/Xservice.php?WSDL", array('trace'=>true));
$cardUID = array('ARN'=>'100000000000002', 'expiryDate'=>2044);
$locationAccess10 = array(
'accessPermission'=>'ALLOW',
'project'=>'CASA BELLA',
'building'=>'MAGNIFICA',
'wing'=>'C',
'door'=>'301'
);
$locationAccess11 = array(
'accessPermission'=>'ALLOW',
'project'=>'CASA BELLA',
'building'=>'MAGNIFICA',
'wing'=>'E',
'door'=>'302'
);
$locationAccessS = array($locationAccess10, $locationAccess11);
$cardInfo1 = array(
'residentID'=>'1000010',
'cardUID'=>$cardUID,
'accessExpiryDate'=>'24/03/2016',
'locationAccess'=>$locationAccessS
);
$cardUID2 = array('ARN'=>'000000011479FFFFFFFFFFFFFFFFFF', 'expiryDate'=>2044);
$locationAccess20 = array(
'accessPermission'=>'ALLOW',
'project'=>'CASA BELLA',
'building'=>'MAGNIFICA',
'wing'=>'C',
'door'=>'302'
);
$locationAccessS2 = array($locationAccess20);
$cardInfo2 = array(
'residentID'=>'1000011',
'cardUID'=>$cardUID2,
'accessExpiryDate'=>'24/03/2016',
'locationAccess'=>$locationAccess20
);
$cardUID3 = array('ARN'=>'100000000000004', 'expiryDate'=>2045);
$cardInfo3 = array(
'residentID'=>'1000013',
'cardUID'=>$cardUID3,
'accessExpiryDate'=>'24/03/2016',
);
$cardInfo = array($cardInfo1,$cardInfo2,$cardInfo3);
try {
$response = $client->AddAccessCardDetails(array('messageId'=>rand(), 'cardInfo'=>$cardInfo));
print_r($response);
}catch (SoapFault $e){
echo '<h2>Debug</h2>';
echo $e->getMessage();
}
echo '<h2>Request</h2>';
echo '<pre>'.htmlspecialchars($client->__getLastRequest(), ENT_QUOTES).'</pre>';
echo '<h2>Response</h2>';
echo '</pre>'.htmlspecialchars($client->__getLastResponse(), ENT_QUOTES).'</pre>';
?>
而服务器在处理参数时,应该将参数作为一个对象来处理,伪代码如下
function AddAccessCardDetails($msg){
$messageId = $msg->messageId;
/*这里$msg->cardInfo可能是一个数组也可能是单独一个元素,取决于客户端传递了一个还是多个cardInfo,详细见WSDL文件*/
$cardInfos = $msg->cardInfo;
if(!is_array($cardInfos)){
$cardInfos = array($cardInfos); //not a array, we make it a array
}
foreach ($cardInfos as $cardInfo){
$resident = $cardInfo->residentID;
$accessExpiryDate = $cardInfo->accessExpiryDate;
$cardUID = $cardInfo->cardUID;
$locationAccessS = $cardInfo->locationAccess;
$ARN = $cardUID->ARN;
$expiryDate = $cardUID->expiryDate;
---------------处理数据---------------------
}
}