Soap php强制转换序列到php数组


Soap php force conversion of sequence to php array

我正在用php测试一些Soap功能

$soapClient = new CustomSoapClient($urlWsdl,[
     'exceptions' => true
     'trace' => true,
     'location' => $soapUrl
]); 
$soapResponse = $soapClient->__call('ProfileLookup',$methodArgs)

CustomSoapClient是一个类,它扩展了基本的SoapClient类,以便记录xml请求和响应(在"__doRequest"方法中)。$soapUrl是测试Soap服务器的位置,它能够通过返回一个或多个结果来回答profilellookup方法

wsdl ($urlWsdl)定义此方法及其返回类型

<wsdl:operation name="ProfileLookup">
        <wsdl:input message="tns:ProfileLookupRequest"/>
        <wsdl:output message="tns:ProfileLookupResponse"/>
    </wsdl:operation>
<wsdl:message name="ProfileLookupResponse">
    <wsdl:part name="LookupResponse" element="n:LookupResponse"/>
</wsdl:message>
 <xs:element name="LookupResponse">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="Result" type="c:ResultStatus"/>
            <xs:element name="ProfileLookups" type="tns:ProfileLookupList"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>
<xs:complexType name="ProfileLookup">
    <xs:sequence>
        <xs:element name="PersonName" type="c:PersonName"/>
        ...
    </xs:sequence>
</xs:complexType>
<xs:complexType name="ProfileLookupList">
    <xs:sequence>
        <xs:element name="ProfileLookup" type="tns:ProfileLookup" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
</xs:complexType>

如果我调用我的Web服务,这个返回多个结果,返回的xml是OK

  <env:Body>
        <ns1:LookupResponse>
            <ns1:Result resultStatusFlag="SUCCESS"/>
            <ns1:ProfileLookups>
                <ns1:ProfileLookup>
                    <ns1:PersonName>
                    </ns1:PersonName>
                </ns1:ProfileLookup>
                <ns1:ProfileLookup>
                    <ns1:PersonName>
                    </ns1:PersonName>
                </ns1:ProfileLookup>
            </ns1:ProfileLookups>
        </ns1:LookupResponse>
    </env:Body>

,这是php中响应的转换方式

[ProfileLookups] => stdClass Object (
    [ProfileLookup] => Array(
            [0] => stdClass Object (
                [PersonName] => stdClass Object()
            ),
            [1] => stdClass Object (
                [PersonName] => stdClass Object()
            )
    )
)

如果我调用web服务只是为了得到一个结果我得到相同的xml结构

<env:Body>
            <ns1:LookupResponse>
                <ns1:Result resultStatusFlag="SUCCESS"/>
                <ns1:ProfileLookups>
                    <ns1:ProfileLookup>
                        <ns1:PersonName>
                        </ns1:PersonName>
                    </ns1:ProfileLookup>
                </ns1:ProfileLookups>
            </ns1:LookupResponse>
        </env:Body>

但是转换为php值是不同的:

   [ProfileLookups] => stdClass Object (
    [ProfileLookup] => stdClass Object(
        [PersonName] => stdClass Object()
    )
   )
如你所见,在第一个例子中,profilellookup是一个类型为"profilellookup"的对象数组,在第二个例子中,profilellookup本身是一个类型为"profilellookup"的对象。

因此,如果只返回一项,下面的代码将导致错误。

foreach($soapResponse->ProfileLookups->ProfileLookup as $profileLookup){
   echo $profileLookup->PersonName->...
}

当然,我可以很容易地测试ProfileLookups-> profilellookup是一个数组还是一个对象,然后强制它是一个数组。但这似乎不是正确的方法,因为我可能在应用程序的每个部分都面临这个问题。

控制SoapClient将xml转换为php值的方式的解决方案是什么?自己解析xml响应会更好吗?像Zend'Soap这样的库能在这个用例中提供帮助吗?我在哪里可以找到SoapClient转换xml到php值的方式的参考文档?

解决方案是在创建SoapClient时启用SOAP_SINGLE_ELEMENT_ARRAYS特性:

$client = new SoapClient($wsdl, array(
    'features' => SOAP_SINGLE_ELEMENT_ARRAYS,
));

我强烈建议您使用WSDL到php生成器,这样您将始终得到您期望的类型的php对象,或者如果您应该得到数组,则得到数组。您应该尝试PackageGenerator项目。