How to generate the following SOAP XML request? - php

The SOAP API I am using, needs the request XML formatted as below:
<SOAP-ENV:Body>
<ns1:functionName/>
<UserID>WEB</UserID>
<Attribute>
<ID>83</ID>
<Value>34343</Value>
</Attribute>
<Attribute>
<ID>84</ID>
<Value>45343</Value>
</Attribute>
</SOAP-ENV:Body>
I have gone through almost all "multiple element" related questions here on StackOverflow but still can't figure it out.
Here is what I am trying at the moment:
$args = new ArrayObject();
$args->UserID = WEB;
$Attribute = new stdClass();
$Attribute->ID = 83;
$Attribute->Value = 34343;
$args->append(new SoapParam($Attribute, 'Attribute'));
$Attribute = new stdClass();
$Attribute->ID = 84;
$Attribute->Value = 45343;
$args->append(new SoapParam($Attribute, 'Attribute'));
$soapClient->functionName($args);
Can someone please help me out with this?

I would advise you to use a WSDL to php generator as you'll deal with abstracted classes that match the required parameter and the operations so you won't have to figure out the correct syntax, it will be automaticcally done by the generated package.
Two generators:
Mine: https://github.com/WsdlToPhp/PackageGenerator
From others: https://github.com/wsdl2phpgenerator/wsdl2phpgenerator
Good luck

Finally managed to figure it out. Hope the below code helps someone:
$args = array();
$args[] = new SoapVar('WEB', XSD_STRING, null, null, 'UserID');
$obj = new stdClass();
$obj->ID = 83;
$obj->Value = 34343;
$args[] = new SoapVar($obj, SOAP_ENC_OBJECT, null, null, 'Attribute');
$obj = new stdClass();
$obj->ID = 84;
$obj->Value = 45343;
$args[] = new SoapVar($obj, SOAP_ENC_OBJECT, null, null, 'Attribute');
$soapClient->functionName(new SoapVar($args, SOAP_ENC_OBJECT));

Related

Add attribute to SoapVar

I am struggling in adding an attribute to a SoapVar-Element.
This is the structure i want to creat:
<SOAP-ENV:Body>
<ns:ServiceRequest>
<ns:Method>PING</ns:Method>
<ns:Property Name="name1">foo</ns:Property>
<ns:Property Name="name2">bar</ns:Property>
</ns:ServiceRequest>
</SOAP-ENV:Body>
but this is all i get:
<SOAP-ENV:Body>
<ns1:ServiceRequest>
<ns1:Method>PING</ns1:Method>
<ns1:Property>foo</ns1:Property>
<ns1:Property>bar</ns1:Property>
</ns1:ServiceRequest>
</SOAP-ENV:Body>
This is my code to create one of the "Property"-nodes:
$node = new SoapVar( 'foo', XSD_STRING, null, null, 'Property', $namespace);
I already tried replacing the 'foo' with an array or an object but nothing worked.
$Property['_'] = 'foo';
$Property['Name'] = 'name1';
$node = new SoapVar( $Property, SOAP_ENC_OBJECT);
... which results in:
<_>foo</_>
<Name>name1</Name>
Let me know if you need more information

Writing xml using php soap library

I have issue and I don't know how to correctly write complex SOAP like this:
<entry>
<key>KEY</key>
<value xsi:type="ns1:Param">
<oid>OID</oid>
</value>
</entry>
Looks like I'm almost done, but I have error like this:
"SOAP-ERROR: Encoding: object has no 'oid' property"
Below is my current code:
$key = new SoapVar('key', XSD_STRING, null, null, 'key');
$oid = new SoapVar('oid', XSD_STRING, null, null, 'oid');
$value = new SoapVar([$oid], SOAP_ENC_OBJECT, 'Param', 'URL', 'value');
$entry = new SoapVar([$key, $value], SOAP_ENC_OBJECT, null, null, 'entry');
Thanks for help in advance!
Finally fixed using this code!:
$key = new SoapVar('KEY', XSD_STRING, null, null, 'key');
$value = new SoapVar(['oid' => 'OID'], XSD_ANYTYPE, 'Param', 'URL', 'value');
$entry = new SoapVar([$key, $value], SOAP_ENC_OBJECT, null, null, 'entry');

PHP SOAP: Passing the same parameters with the same name

I can't get this to work. I've read a bunch on it on the forum already but I just can't seem to find the solution to this.
I've created a SOAP call and it's working etc., but when I try to pass the same parameters multiple times it just overwrites itself which is logical.
The code has to be done with objects only so I've used stdClass()
Example of the code below:
$relationCreate = new stdClass();
$relationCreate->credentials = new stdClass();
$relationCreate->credentials->ApiKey = ''; //Removed for security reasons.
$relationCreate->credentials->DatabaseId = ''; //Removed for security reasons.;
$relationCreate->credentials->UserId = ''; //Removed for security reasons.;
$relationCreate->parentRelationId = $company;
$relationCreate->relationEntityTypeId = "84a15869-5b88-49df-ad47-7b6f9648ae07";
//surname
$relationCreate->relationFieldValues = new stdClass();
$relationCreate->relationFieldValues->PvFieldValueData = new stdClass();
$relationCreate->relationFieldValues->PvFieldValueData->Id = "9d549512-dc8a-4774-84d1-27a349e8a8c7";
$relationCreate->relationFieldValues->PvFieldValueData->Value = $name;
// This one has to repeat which does not work. Which is logical
$relationCreate->relationFieldValues = new stdClass();
$relationCreate->relationFieldValues->PvFieldValueData = new stdClass();
$relationCreate->relationFieldValues->PvFieldValueData->Id = "9d549512-dc8a-4774-84d1-27a349e8a8c7";
$relationCreate->relationFieldValues->PvFieldValueData->Value = $name;
The soap should look as followed I tested this using SoapUI:
<api:fieldValues>
<!--Zero or more repetitions:-->
<api:PvFieldValueData>
<api:Id>c2fcb464-92e6-4227-8672-56f88e219279</api:Id>
<!--Optional:-->
<api:Value>Test</api:Value>
</api:PvFieldValueData>
</api:fieldValues>
<api:fieldValues>
<!--Zero or more repetitions:-->
<api:PvFieldValueData>
<api:Id>d900fe23-8549-451c-82f4-c5918cb3abbb</api:Id>
<!--Optional:-->
<api:Value>Test</api:Value>
</api:PvFieldValueData>
</api:fieldValues>
WSDL file for reference: https://api.perfectview.nl/V1/perfectview.asmx?WSDL
References:
PHP SoapClient - Multiple attributes with the same key
SoapClient: how to pass multiple elements with same name?
You can try to put the items into an array.
Example:
$relationCreate->relationFieldValues = [];
// repeat this in a foreach loop:
$item = new stdClass();
$item->PvFieldValueData = new stdClass();
$item->PvFieldValueData->Id = $uuid;
$item->PvFieldValueData->Value = $name;
// Add item to values
$relationCreate->relationFieldValues[] = $item;

PHP Soap complex params with repeated keys

I need to generate the following XML
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://services.bloomberg.com/datalicense/dlws/ps/20071001">
<SOAP-ENV:Body>
<ns1:submitGetHistoryRequest>
<ns1:headers>
<ns1:daterange>
<ns1:period>
<ns1:start>2018-05-08</ns1:start>
<ns1:end>2018-05-08</ns1:end>
</ns1:period>
</ns1:daterange>
</ns1:headers>
<ns1:fields>
<ns1:field>PX_LAST</ns1:field>
</ns1:fields>
<ns1:instruments>
<ns1:instrument>
<ns1:id>US0000000002</ns1:id>
<ns1:yellowkey>Equity</ns1:yellowkey>
<ns1:type>ISIN</ns1:type>
</ns1:instrument>
<ns1:instrument>
<ns1:id>US0000000001</ns1:id>
<ns1:yellowkey>Equity</ns1:yellowkey>
<ns1:type>ISIN</ns1:type>
</ns1:instrument>
</ns1:instruments>
</ns1:submitGetHistoryRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I use PHP 7.1.17 and SoapClient.
I can not pass options to SoapClient, as the instrument key is repeated and PHP's associated array can not have same key twice. I tried constructing object and setting instrument properties as SoapVar, but it generates incorrect XML. Here is code and result:
$options = new \stdClass();
$options->headers = new \stdClass();
$options->headers->daterange = new \stdClass();
$options->headers->daterange->period = new \stdClass();
$options->headers->daterange->period->start = '2018-05-08';
$options->headers->daterange->period->end = '2018-05-08';
$options->fields = new \stdClass();
$options->fields->field = 'PX_LAST';
//first instrument
$instrument = new \stdClass();
$instrument->id = 'US0000000002';
$instrument->type = 'ISIN';
$instrument->yellowkey = 'Equity';
$options->instruments[] = new \SoapVar(
$instrument,
SOAP_ENC_OBJECT,
'stdClass',
"http://soapinterop.org/xsd",
"instrument"
);
//second instrument
$instrument = new \stdClass();
$instrument->id = 'US0000000001';
$instrument->type = 'ISIN';
$instrument->yellowkey = 'Equity';
$options->instruments[] = new \SoapVar(
$instrument,
SOAP_ENC_OBJECT,
'stdClass',
"http://soapinterop.org/xsd",
"instrument"
);
<ns1:instruments/> remains empty in resulting XML:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://services.bloomberg.com/datalicense/dlws/ps/20071001">
<SOAP-ENV:Body>
<ns1:submitGetHistoryRequest>
<ns1:headers>
<ns1:daterange>
<ns1:period>
<ns1:start>2018-05-08</ns1:start>
<ns1:end>2018-05-08</ns1:end>
</ns1:period>
</ns1:daterange>
</ns1:headers>
<ns1:fields>
<ns1:field>PX_LAST</ns1:field>
</ns1:fields>
<ns1:instruments/>
</ns1:submitGetHistoryRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
How can I pass options to SoapClient, to generate XML with repeated instrument keys?
I solved this. Turns out when you pass an ordered array (not associative one) as object's property, as many XML nodes are generated using that property's name, as number of elements in the array. So instead of building SoapVar objects and putting them into instruments[] array, I just assigned array of instruments to instruments as instrument property:
$options->instruments = new \stdClass();
//first instrument
$instrument = new \stdClass();
$instrument->id = 'US0000000002';
$instrument->type = 'ISIN';
$instrument->yellowkey = 'Equity';
$options->instruments->instrument[] = $instrument;
//second instrument
$instrument = new \stdClass();
$instrument->id = 'US0000000001';
$instrument->type = 'ISIN';
$instrument->yellowkey = 'Equity';
$options->instruments->instrument[] = $instrument;
I build instruments in a foreach loop. Btw converting array to object instead of building stdClass also works fine:
$options->instruments->instrument[] = (object)[
'id' => 'US0000000001',
'type' => 'ISIN',
'yellowkey' => 'Equity'
]

Using complex structure with SOAP

The problem is that I cannot succeed to send an array of class through SOAP to a specific web service that I cannot change his structure.
Here below you'll see the schema of the Soap function:
http://www.elyotech.com/share/yoni/forum/developpeznet-soap.jpg
Here you'll find the code I'm corresponding to it:
$s = new soapclient($URL_WEBSERVICE,array('wsdl'=>true,"trace"=>true));
$params = new stdClass();
$params->loginInfo = new stdClass();
$params->loginInfo->UserName = 'username';
$params->loginInfo->Password = 'password';
$params->loginInfo->LanguageCode = 'en';
$params->reservation = new stdClass();
$params->reservation->EmailRecipient2 = 'yonia#yopmail.com';
$params->reservation->EmailRecipient3 = 'yonia2#yopmail.com';
$params->reservation->FirstName = 'Yoni'
foreach($extras as $id=>$extra)
{
$params->Extras[$id]= new stdClass();
$params->Extras[$id]->SelectedExtra = new stdClass();
$params->Extras[$id]->ExtensionData = new stdClass();
$params->Extras[$id]->SelectedExtra->Amount = 1;
$params->Extras[$id]->SelectedExtra->ID = $extra;
}
Here is the SOAP request that is sent:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/">
<SOAP-ENV:Body>
<ns1:CreateReservation>
<ns1:loginInfo>
<ns1:UserName>monusername</ns1:UserName>
<ns1:Password>monpass</ns1:Password>
<ns1:LanguageCode>en</ns1:LanguageCode>
</ns1:loginInfo>
<ns1:reservation>
<ns1:EmailRecipient2>yonia#yopmail.com</ns1:EmailRecipient2>
<ns1:EmailRecipient3>yonia2#yopmail.com</ns1:EmailRecipient3>
<ns1:FirstName>Yoni</ns1:FirstName>
</ns1:reservation>
</ns1:CreateReservation>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
In this Soap request, I cannot find the Extras array of objects.
Do you have any idea of how I should create my object in order to send it correctly?

Categories