9

I have following code:

$telnums = array(10, 20, 30);
$obj = new StdClass();
$obj->telnums = new StdClass();
foreach ($telnums as $telnum) {
    $obj->telnums = $telnum;
}

call_user_func(array($this->client, 'createDomain'), new SoapVar($obj, SOAP_ENC_OBJECT));

There $this->client is an instance of SoapClient class.

And it generates following request:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="...">
    <SOAP-ENV:Body>
        <ns1:createDomain>
            <createDomainRequest>
                <telnums>30</telnums>
            </createDomainRequest>
        </ns1:createDomain>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

But I need

            <createDomainRequest>
                <telnums>10</telnums>
                <telnums>20</telnums>
                <telnums>30</telnums>
            </createDomainRequest>

How I can achieve this?

P.S.: PHP 5.2.6-3ubuntu4.5 with Suhosin-Patch 0.9.6.2 (cli) (built: Jan 6 2010 22:25:33)

Thanks in advance!

Slava Semushin
  • 14,904
  • 7
  • 53
  • 69

6 Answers6

15

I had landed into a similar scenario recently and I found this pattern usually does the trick.

$obj = new StdClass();
foreach ($telnums as $telnum) {
    $obj->telnums[] = $telnum;
}

The reason this works is because it closely emulates the same data structure as prescribed by your WSDL

Akshay Agarwal
  • 1,959
  • 1
  • 16
  • 14
9

The correct answer should have been:

$options = array(
  'createDomainRequest' => array(
    'telnums' => array(
      '10',
      '20',
      '30'
    )
  )
);

:)

denormalizer
  • 2,186
  • 3
  • 24
  • 36
  • 3
    This is actually incorrect as it results in: <0>100> <1>201> <2>302> – quickthyme Mar 01 '13 at 15:54
  • 1
    The problem here is that associative arrays in php can't have identical keys for obvious reasons. For non SoapClient situations, I managed to work around this by building a custom array to xml conversion class that can handle multiple child elements with the same name, and produces the correct xml output. So, how can we fix the SoapClient so that it can do that as well? The override on __doRequest() is undesirable. Surely this has been encountered before... – quickthyme Mar 01 '13 at 16:04
  • 4
    Only that it doesn't produce XML that matches what the question stated. This method works fine if you can control the parsing end, but usually remote services tend to be very explicit and don't handle variations in the document structure very well. – quickthyme May 14 '13 at 00:41
  • Have you tried this method before? It works for me - and I don't control the parsing end. Parsers seem to like them just fine. – denormalizer May 15 '13 at 04:03
  • 2
    I have, and it produces XML output like that which I wrote in my initial comment. Maybe some remote services are designed to accept this discrepancy, but most of the ones I have encountered do not. When subscribing to SOAP services, WSDLs describe exactly how the XML elements are to be ordered. Unfortunately, PHP's built-in SoapClient is subject to the limitations of PHP's associative arrays, in that you can't add more than one key of the same name. The only way to work around it (that I know of currently) is to modify the XML document after-the-fact. – quickthyme May 15 '13 at 06:43
  • Thanks. Works fine for 5 8 9 – Kamal Pundir Jul 08 '15 at 08:33
  • This is the proper way to do this. Tested and works. – Matt K Sep 27 '16 at 19:25
1

It is a pain in the buttock to find a working solution, but eventually it's not that hard. Even surprisingly easy and neat by using SoapParam's:

$soapClient = new SoapClient($wsdl);
$soapClient->__call('createDomain', array(
    new SoapParam('10', 'telnums'),
    new SoapParam('20', 'telnums'),
    new SoapParam('30', 'telnums'),
));
Klaas van der Weij
  • 1,065
  • 10
  • 13
0

Here is the code format that I used:

$wsdl = 'https://your.api/path?wsdl';
$client = new SoapClient($wsdl);
$multipleSearchValues = [1, 2, 3, 4];
$queryData = ['yourFieldName' => $multipleSearchValues];
$results = $client->YourApiMethod($queryData);
print_r($results);
diamondsea
  • 2,980
  • 1
  • 12
  • 9
-1

Fixed it by extends SoapClient and overrides __doRequest() method where I modify request as descibed here: http://www.php.net/manual/en/soapclient.dorequest.php#57995

Looks terrible for me, but it works "right here, right now".

Slava Semushin
  • 14,904
  • 7
  • 53
  • 69
  • Ugh. This is horrible, but as far as I can tell, it's the only way to make this work in some cases. It seems like this is a very common problem, which makes me wonder why this hasn't been addressed in the SoapClient already?? – quickthyme Mar 01 '13 at 16:52
-1
$telnums=array(10, 20, 30);
$createDomainRequest=array('createDomainRequest' => array(
  'telnums' => $telnums)
);
Obsidian Age
  • 41,205
  • 10
  • 48
  • 71
Jesy
  • 53
  • 7