PHP:如何保留SOAP响应的结构?

时间:2013-04-05 14:55:18

标签: php soap response

我有一个关于PHP中的SOAP调用的问题。有一个名为“DoBulkOperation”的Web服务,它接收任何内容列表,执行某些操作,并返回一个列表,其中包含有关它所执行操作的信息。这里重要的是,请求的每个列表元素在同一索引的响应中都有其对应部分。

我得到的回应是这样的:

<Body>
  <DoBulkOperationResponse>
    <items>
      <OperationResponse>
        <result>17</result>
      </OperationResponse>
      <Error>Some error occured</Error>
      <OperationResponse>
        <result>18</result>
      </OperationResponse>
      <OperationResponse>
        <result>19</result>
      </OperationResponse>
      <OperationResponse>
        <result>20</result>
      </OperationResponse>
    </items>
  </DoBulkOperationResponse>
</Body>

对我的请求的正确回应。现在,我可以说,请求中的第二个列表元素有问题。

我从PHP SoapClient获得的不是我所期望的:

object(stdClass)#49 (1) {
  ["items"]=>
  object(stdClass)#51 (2) {
    ["OperationResponse"]=>
    array(4) {
      [0]=>
      object(stdClass)#53 (1) {
        ["customerID"]=>
        int(17)
      }
      [1]=>
      object(stdClass)#52 (1) {
        ["customerID"]=>
        int(18)
      }
      [2]=>
      object(stdClass)#50 (1) {
        ["customerID"]=>
        int(19)
      }
      [3]=>
      object(stdClass)#54 (1) {
        ["customerID"]=>
        int(20)
      }
    }
    ["Error"]=>
    string(17) "Some error occured"
  }
}

元素的顺序完全被破坏了。现在,无法确定哪个请求元素会导致哪个响应元素。

在WSDL中,“items”被定义为序列。

有没有办法强制SoapClient实例保留响应的结构?

致以最诚挚的问候,

马库斯

1 个答案:

答案 0 :(得分:5)

这里有几个选项,但是为了得到明确的答案,你应该为这个电话提供WSDL。

强制PHP SoapClient始终返回已定义的数组。

设置或添加array('features' => SOAP_SINGLE_ELEMENT_ARRAYS)作为SoapClient的选项。只有遇到多个元素时,它才会阻止结果产生数组。从我认为PHP做的内部:在第一次元素遭遇,它刚刚创建,并在下次遇到时,第一个元素被移动到一个数组,第二个元素然后被添加。

这可能已经解释了您所看到的结构,并且可能能够解决它。

使用带有预定义预期结构的对象的类映射。

您必须在WSDL中找到ComplexType结构的名称,然后可以创建用于这些而不是stdClass的PHP类。这对所有内容都非常有用,因为您的IDE可以为您提供自动完成功能,您可以使用get_class()实际查看您正在处理的元素。另一方面,您无法创建一个正确充当XML中items结构的PHP对象,因此这可能只是装饰性的,但它是必要的......

在自定义类中使用magic __set()来干扰创建结果。

您可以创建一个用作items的自定义类,它将设置所有属性。在魔术功能中,您可以尝试推送数据。至少你可以用一些输出来调试它。

跟踪请求并直接访问XML结果。

在选项数组中设置选项trace => true,然后使用SoapClient::__getLastResponse

为失败做好准备。

PHP可能无法将您获得的XML结构转换为正确的结果。我会责怪你提供的Soap API。通常会提供将某种ID附加到请求并在结果上重用此ID以使客户端能够识别其内容。至少“按请求顺序”返回的结构应始终返回相同的项目,并将结果传递到内部,如:

<OperationResponse>
    <result>17</result>
</OperationResponse>
<OperationResponse>
    <Error>Some error occured</Error>
</OperationResponse>