我在php中使用soap调用web服务,但我在xml中获得错误作为服务器的响应。
问题是,当为请求创建xml时,Php在xml中引入id,然后无论它在哪里找到相同的节点,它只是传递id作为引用。
如:-
<ns1:ChargeBU id="ref1">
<ns1:ChargeBreakUp>
<ns1:PriceId>0</ns1:PriceId>
<ns1:ChargeType>TboMarkup</ns1:ChargeType>
<ns1:Amount>35</ns1:Amount>
</ns1:ChargeBreakUp><ns1:ChargeBreakUp>
<ns1:PriceId>0</ns1:PriceId>
<ns1:ChargeType>OtherCharges</ns1:ChargeType>
<ns1:Amount>0.00</ns1:Amount>
</ns1:ChargeBreakUp>
</ns1:ChargeBU>
然后当它找到相同的节点时它会执行
<ns1:ChargeBU href="#ref1"/>
那么我怎么能防止这种情况,使它再次包含完整节点,而不仅仅是传递引用??
我有同样的问题,但无法找出在SoapClient内做不同的事情来修复它。我最终重写__doRequest()在发送之前修改xml以从元素中删除引用id并将引用元素替换为它们引用的元素。如果你这样做,一定要修复__getLastRequest(),如下所示。
编辑:在发送之前使用unserialize(serialize($input))
似乎已经为我解决了这个问题。
您可以创建该数组的新副本(实例),以防止PHP对相同的值使用ref。
例如,我们有:$item = array(
"id" => 1,
"name" => "test value"
);
和请求/响应:
$response = array(
"item1" => $item,
"item2" => $item
);
默认情况下,php将item2
的值替换为对item1
的引用(两个项都指向同一个数组)
为了防止这种行为,我们需要用相同的结构创建两个不同的项,类似于:
function copyArray($source){
$result = array();
foreach($source as $key => $item){
$result[$key] = (is_array($item) ? copyArray($item) : $item);
}
return $result;
}
和请求/响应:
$response = array(
"item1" => copyArray($item),
"item2" => copyArray($item)
);
相同的by结构项实际上是内存中不同的数组在这种情况下PHP不会生成任何ref
我做了一些研究,SOAP扩展、nuSOAP、WSO2从2010年开始就不支持了。它们充满了未修复的bug,我不建议使用它们。
使用Zend 2 SOAP代替,它不使用任何不受支持的扩展,或者如果您是Symfony的粉丝,那么尝试简单的SOAP绑定,它试图修复SOAP扩展的错误。不要重新发明轮子!
我稍微改变了一下这个函数,因为。如果$source不是一个数组,那么在foreach
中会有一个小问题。function copyArray(Array $source){
$result = array();
if($source) { // not for empty arrays
foreach($source as $key => $item){
$result[$key] = (is_array($item) ? copyArray($item) : $item);
}
}
return $result;
}