|
oops. missed an important
correction: Replace the section (2) below of rolling your own with the
following:
2) a
better way, that I found, is to use the soapval() class when it comes to
creating your own payload. soapval allows you to specify an object type
and value for an element as well as attributes, if the element takes
attributes.
Lets
assume our data is as :
<search
name='some-name'>
<addresstype value='home'>
<address>some-address</address>
<street>123 lane</street>
<city>some city</city>
<zip>12345</zip>
</address>
</addresstype>
</search>
Again,
since we have a structured data set we work our way from the inner most elements
to the outter ones.
$addrValue
= array ('address' => 'some-address', 'street' => '123 lane', 'city' =>
'some city', 'zip' => '12345');
$address =
new soapval('addresstype', 'AddressType', $addrValue, false, false,
array('value' => 'home'));
$searchMsg
= new soapval('search', 'Search', $address, false, false, array('name' =>
'some-name');
Note, I am
giving a false value for element and value namespace. If you need to declare
element/value namespace declare them. Now you have to serialize the data yourself since the
call() method doesn't at this point seem to handle serialization of soapval
objects from lcient side correctyl. So, now you
do:
$xml =
$flagFileUpdate->serialize('literal');
create the client and make the
call:
$client =
new soapclient($endPoint, $wsdl = true);
$response
= $client->call('SearchOperation', $xml);
[the rest stays the
same]
After a
couple of weeks of banging away, I have been able to get complex data handled
from the client side of things, and here is a brief summary of what I
found. I will basically provide examples of what I did going from a
payload data definition (in xml) to client php code.
Assume
that you have a service that takes in a payload as in:
<search>
<name>some-name</name>
<home>
<address>some-address</address>
<street>123 lane</street>
<city>some city</city>
<zip>12345</zip>
<state>CA</state>
</address>
</home>
</search>
To code
this in a client php you can package data with a series of associateve
arrays. Start with the inner most data elements and keep wrapping them up
in arrays() as you move to the outer elements. So, for above the following
should work:
$address =
array('street' => '123 lane', 'city' => 'some city', 'zip' => '12345',
'state' => 'CA');
$home =
array('home' => $address);
$search =
array('name' => 'some-name', 'home' => $home);
Your
message data is now $search, so you can use it as in:
$client =
new soapclient($someEndPoint, $wsdl = true);
$response
= $client->call('SearchOperation', $search);
If you
need any special handling of the data elements, then you basically have to roll
your own payload. You can do this in two ways : 1) if you can decipher the
wsdl (either by eye or via a tool), you can then construct the entire xml
payload data and then do the following:
$xmlString = ....// hand coded as a string with all the
elements/attributes/values
$client =
new soapclient($endPoint, $wsdl=true);
$soapmsg =
$client->serializeEnvelope($xmlString, '', array(), 'document',
'literal'); // assuming .net doc/literal style
$response
= $client->('SearchOperation', $soapmsg, ....)
Look at
the serializeEnvelope's documentation for exact definition. Also, see here
for a more concrete example:
2) a
better way, that I found, is to use the soapval() class when it comes to
creating your own payload. soapval allows you to specify an object type
and value for an element as well as attributes, if the element takes
attributes.
Lets
assume our data is as :
<search
name='some-name'>
<addresstype value='home'>
<address>some-address</address>
<street>123 lane</street>
<city>some city</city>
<zip>12345</zip>
</address>
</addresstype>
</search>
Again,
since we have a structured data set we work our way from the inner most elements
to the outter ones.
$addrValue
= array ('address' => 'some-address', 'street' => '123 lane', 'city' =>
'some city', 'zip' => '12345');
$address =
new soapval('addresstype', 'AddressType', $addrValue, false, false,
array('value' => 'home'));
$searchMsg
= new soapval('search', 'Search', $address, false, false, array('name' =>
'some-name');
Note, I am
giving a false value for element and value namespace. If you need to declare
element/value namespace declare them. Now create the client and make the
call:
$client =
new soapclient($endPoint, $wsdl = true);
$response
= $client->call('SearchOperation', $searchMsg);
One other
note, in my case the data elements in the message required a 'tns' prefix, so if
you have:
<tns:search name='some-name'>
<tns:addresstype
value='home'>
<tns:address>some-address</tns:address>
<tns:street>123 lane</tns:street>
<tns:city>some city</tns:city>
<tns:zip>12345</tns:zip>
</tns:address>
</tns:addresstype>
</tns:search>
All you
have to do is to add the 'tns' string in front of the names where you are
creating data with the soapval class. As an example:
$address =
new soapval('tns:addresstype', 'AddressType', ....)
That's
it.
Hope this
helps.
Mohsen
|