PHP SOAP - 摆脱BOGUS标签

时间:2014-02-12 19:20:51

标签: php soap

在我的SOAP调用中,我需要有多个具有相同名称的元素。

我在这篇文章中找到了一种方法:http://andrecatita.com/code-snippets/php-soap-repeated-element-name/

Hoewever,由于某种原因,我得到的是BOGUS代码,而不是所需的TranItem

php代码是:

$itemParams = new ArrayObject();
$items = new ArrayObject();
$tranItems = new stdClass();

$itemParams[0]->ItemId = '1234';
$itemParams[0]->Amount = '1';
$itemParams[0]->Price = '2000';
$itemParams[0]->TranRules = array('TranRule' => $itemRule);

$itemParams[1]->ItemId = '55555';
$itemParams[1]->Amount = '1';
$itemParams[1]->Price = '2000';
$itemParams[1]->TranRules = array('TranRule' => $itemRule);

$items->append($itemParams[0]);
$items->append($itemParams[1]);

$tranItems->TranItems = new SoapVar($items, SOAP_ENC_OBJECT, NULL, NULL, 'TranItems',$namespace);
...
...

 $trans = array(
   'TranItems' => $tranItems->TranItems
);

输出:

         <ns1:TranItems>
            <BOGUS>
              <ItemId>1234</ItemId>
              <Amount>1</Amount>
              <Price>2000</Price>
              <TranRules>
                <item>
                  <key>TranRule</key>
                  <value/>
                </item>
              </TranRules>
            </BOGUS>
            <BOGUS>
              <ItemId>55555</ItemId>
              <Amount>1</Amount>
              <Price>2000</Price>
              <TranRules>
                <item>
                  <key>TranRule</key>
                  <value/>
                </item>
              </TranRules>
            </BOGUS>
          </ns1:TranItems>

如何摆脱BOGUS元素并在其中包含TranItem?

2 个答案:

答案 0 :(得分:1)

从此服务器:

$server = new SoapServer(null, array(
    'uri'       => 'http://test/',
));

$server->addFunction('test');

function test(){
    $itemParams = new ArrayObject();
    $items = array();

    $itemParams[0]->ItemId = '1234';
    $itemParams[0]->Amount = '1';
    $itemParams[0]->Price = '2000';
    $itemParams[0]->TranRules = array('TranRule' => 1);

    $itemParams[1]->ItemId = '55555';
    $itemParams[1]->Amount = '1';
    $itemParams[1]->Price = '2000';
    $itemParams[1]->TranRules = array('TranRule' => 2);

    $items[] = new SoapVar($itemParams[0], SOAP_ENC_OBJECT);
    $items[] = new SoapVar($itemParams[1], SOAP_ENC_OBJECT);

    return new SoapVar($items, SOAP_ENC_OBJECT, NULL, NULL, 'TranItems');
}

$server->handle();

有了这个客户:

$client = new SoapClient(null, array(
    'location' => 'http://localhost/server.php',
    'uri'       => 'http://test/',
    'trace'     => true
));

$p = $client->test();

$resp = $client->__getLastResponse();
$dom = new DOMDocument();
$dom->formatOutput = true;
$dom->preserveWhiteSpace = false;
$dom->loadXML($resp);
print '<pre>';
var_dump($p);
print htmlspecialchars($dom->saveXML());

我收到了这个回复:

object(stdClass)[2]
  public 'TranItems' => 
    array (size=2)
      0 => 
        object(stdClass)[3]
          public 'ItemId' => string '1234' (length=4)
          public 'Amount' => string '1' (length=1)
          public 'Price' => string '2000' (length=4)
          public 'TranRules' => 
            array (size=1)
              ...
      1 => 
        object(stdClass)[4]
          public 'ItemId' => string '55555' (length=5)
          public 'Amount' => string '1' (length=1)
          public 'Price' => string '2000' (length=4)
          public 'TranRules' => 
            array (size=1)
              ...
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <ns1:testResponse>
      <ns1:TranItems xsi:type="SOAP-ENC:Struct">
        <TranItems xsi:type="SOAP-ENC:Struct">
          <ItemId xsi:type="xsd:string">1234</ItemId>
          <Amount xsi:type="xsd:string">1</Amount>
          <Price xsi:type="xsd:string">2000</Price>
          <TranRules xsi:type="ns2:Map">
            <item>
              <key xsi:type="xsd:string">TranRule</key>
              <value xsi:type="xsd:int">1</value>
            </item>
          </TranRules>
        </TranItems>
        <TranItems xsi:type="SOAP-ENC:Struct">
          <ItemId xsi:type="xsd:string">55555</ItemId>
          <Amount xsi:type="xsd:string">1</Amount>
          <Price xsi:type="xsd:string">2000</Price>
          <TranRules xsi:type="ns2:Map">
            <item>
              <key xsi:type="xsd:string">TranRule</key>
              <value xsi:type="xsd:int">2</value>
            </item>
          </TranRules>
        </TranItems>
      </ns1:TranItems>
    </ns1:testResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

稍加修改:

$items[] = new SoapVar($itemParams[0], SOAP_ENC_OBJECT, 'TransItem');
$items[] = new SoapVar($itemParams[1], SOAP_ENC_OBJECT, 'TransItem');

return new SoapVar($items, SOAP_ENC_ARRAY, 'TransItem', null);

你会得到:

array (size=2)
  0 => 
    object(stdClass)[2]
      public 'ItemId' => string '1234' (length=4)
      public 'Amount' => string '1' (length=1)
      public 'Price' => string '2000' (length=4)
      public 'TranRules' => 
        array (size=1)
          'TranRule' => int 1
  1 => 
    object(stdClass)[3]
      public 'ItemId' => string '55555' (length=5)
      public 'Amount' => string '1' (length=1)
      public 'Price' => string '2000' (length=4)
      public 'TranRules' => 
        array (size=1)
          'TranRule' => int 2
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://xml.apache.org/xml-soap" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <ns1:testResponse>
      <return SOAP-ENC:arrayType="TransItem[2]" xsi:type="TransItem">
        <item xsi:type="TransItem">
          <ItemId xsi:type="xsd:string">1234</ItemId>
          <Amount xsi:type="xsd:string">1</Amount>
          <Price xsi:type="xsd:string">2000</Price>
          <TranRules xsi:type="ns2:Map">
            <item>
              <key xsi:type="xsd:string">TranRule</key>
              <value xsi:type="xsd:int">1</value>
            </item>
          </TranRules>
        </item>
        <item xsi:type="TransItem">
          <ItemId xsi:type="xsd:string">55555</ItemId>
          <Amount xsi:type="xsd:string">1</Amount>
          <Price xsi:type="xsd:string">2000</Price>
          <TranRules xsi:type="ns2:Map">
            <item>
              <key xsi:type="xsd:string">TranRule</key>
              <value xsi:type="xsd:int">2</value>
            </item>
          </TranRules>
        </item>
      </return>
    </ns1:testResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

说明:

肥皂是作为跨语言传输协议开发的。在大多数语言中,没有关联数组这样的东西。这就是为什么你必须将$itemParams[0]编码为对象的原因。 soap的大多数目标语言(如Java)具有强类型,因此当您不为soap编码器提供类型时,它将生成一个。数组也是如此。在强类型语言中,每个数组只能包含一种对象。总结一下:你将php关联数组编码为TYPE的对象,其中TYPE将成为节点名称,然后如果返回多个元素:将它们编码为包含特定TYPE对象的soap数组。未编码的数组(因为它可以包含多种不同类型)被转换为具有多个项目节点的映射,每个节点都具有关键节点和值节点。

改变这个:

$items[] = new SoapVar($itemParams[0], SOAP_ENC_OBJECT, null, null, 'TranItems');

到那个:

$items[] = new SoapVar($itemParams[0], SOAP_ENC_OBJECT);

你会得到BOGUS。

答案 1 :(得分:1)

我最终得到了这个有效的代码 - 可能不是最好的解决方案,但这是唯一对我有用的代码:

class Item {
    public $ItemId;
    public $Amount;
    public $Price;
    public $TranRules;
}

class TranRule {
    public $RuleId;
    public $Value;
}

$rule1 = new TranRule();
$rule1->RuleId = '2';
$rule1->Value = '300';
$rule1 = new SoapVar($rule1, SOAP_ENC_OBJECT, NULL, NULL, 'TranRule', 'http://gate.ibod.cz/v1/api.svc');

$return_array = new ArrayObject();

$new_item  = new Item();
$new_item->ItemId = '13245';
$new_item->Amount = "1";
$new_item->Price = "500";
$new_item->TranRules = $rule1;
$new_item = new SoapVar($new_item, SOAP_ENC_OBJECT, null, null, 'TranItem');
$return_array->append($new_item);

$new_item  = new Item();
$new_item->ItemId = '456789';
$new_item->Amount = "1";
$new_item->Price = "20000";
$new_item->TranRules = $rule2;
$new_item = new SoapVar($new_item, SOAP_ENC_OBJECT, null, null, 'TranItem');
$return_array->append($new_item);

$tranItems = new stdClass();
$tranItems->TranItems = new SoapVar($return_array, SOAP_ENC_OBJECT, NULL, NULL, 'TranItems');