【问题标题】:Soap php force conversion of sequence to php arraySoap php强制将序列转换为php数组
【发布时间】:2016-10-24 14:07:36
【问题描述】:

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

$soapClient = new CustomSoapClient($urlWsdl,[
     'exceptions' => true
     'trace' => true,
     'location' => $soapUrl
]); 

$soapResponse = $soapClient->__call('ProfileLookup',$methodArgs)

CustomSoapClient 是一个扩展基础 SoapClient 类的类,用于记录 xml 请求和响应(在“__doRequest”方法中。 $soapUrl 是一个测试 Soap 服务器的位置,它能够通过返回一个或多个结果来响应 ProfileLookup 方法

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 正常

  <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()
    )
   )

如您所见,在第一个示例中,ProfileLookup 是“ProfileLookup”类型的对象数组,而在第二个示例中,ProfileLookup 本身就是“ProfileLookup”类型的对象。

所以如果只返回一项,下面的代码会导致错误。

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

当然,我可以轻松测试 ProfileLookups->ProfileLookup 是数组还是对象,然后强制它成为数组。但这似乎不是正确的方法,因为我在应用程序的每个部分都可能遇到这个问题。

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

【问题讨论】:

    标签: php arrays xml soap


    【解决方案1】:

    解决方法是在创建SoapClient时开启SOAP_SINGLE_ELEMENT_ARRAYS功能:

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2017-06-24
        • 1970-01-01
        • 1970-01-01
        • 2017-05-12
        • 1970-01-01
        • 2012-05-18
        • 1970-01-01
        • 2019-04-10
        • 2014-11-19
        相关资源
        最近更新 更多