SoapVar/Param and nested, repeated elements in SOAP - php

My goal is to be able to create a soap request that can contain items like so:
<flexFields>
<names>
<names>IAG Group</names>
<names>Ticket #</names>
</names>
</flexFields>
However, every combination of soapvar and soapparam I've been able to think up either makes it impossible for me to duplicate the nested 'names' tag. I can get 1 sub tag like so:
$flexFields = array(
'names'=> new SoapVar(
new SoapVar(array('names'=>'IAG Group'),SOAP_ENC_OBJECT),
SOAP_ENC_OBJECT)
);
This generates:
<flexFields xsi:type="ns2:SoapNamedValues">
<names xsi:type="names">
<names xsi:type="xsd:string">IAG Group</names>
</names>
</flexFields>
But any attempt I make to get the names tag to repeat either generates a dreaded BOGUS element if I use SOAP_ENC_OBJECT, or wraps every item in another 'item' element if I use SOAP_ENC_ARRAY, which is also not desirable.
I know I could just manually create what I want and load it with XSD_ANYXML, but that is getting close to the line of defeating the purpose of using the SOAP library.
Can anyone provide an example of just how to perfectly balance the soapvar/soapparam + array nesting to get this to actually work? Or am I attempting the impossible with PHP's SOAP library?

I have a similar problem, try this:
$Names=array();
$Names[]=new SoapVar("IAG Group",XSD_STRING,null,null,'names');
$Names[]=new SoapVar("Ticket #",XSD_STRING,null,null,'names');
$BigNames=new SoapVar($Names,SOAP_ENC_OBJECT,null,null,'Names');
This creates and array of of SoapVar objects ($Names) and places them in the BigNames object, creating an output like this:
<Names>
<names>IAG Group</names>
<names>Ticket #</names>
</Names>
You can then create another SoapVar object for FlexFields, but for some reason you can't place a SoapVar object directly into another, it has to be stored in an array...
I want to do this:
$FlexFields=new SoapVar($BigNames,SOAP_ENC_OBJECT,null,null,'FlexFields');
This works:
$FF=array($BigNames);
$FlexFields=new SoapVar($FF,SOAP_ENC_OBJECT,null,null,'FlexFields');

I ran into the BOGUS tag problem also. My solution involved using an ArrayObject in place of array primitives. The objects are all then converted to SoapVar objects. It seems the soap library really wants to deal with objects everywhere. I have a more complete writeup here:
http://www.fischco.org/blog/2011/3/26/php-soapserver-objects-arrays-and-encoding.html

Related

php create several objects within object

I am trying to make a soap request and it needs to have this structure
$requestBody=new sendDataExtraccionRequest(new sendDataExtraccionSubterranea("18-09-2020","00:02:01",1234567891,12345678.12,12345678.12),
new sendDataExtraccionSubterranea("18-09-2020","00:03:01",1234567891,12345678.12,12345678.12));
thought that by creating an array with each object and then cast it should do, but getting an error on the soap call that the date field is missing
$array_datos[] = new sendDataExtraccionSubterranea("03-02-2021","00:02:01",1234567891,12345678.12,12345678.12);
$array_datos[] = new sendDataExtraccionSubterranea("03-02-2021","00:03:01",1234567891,12345678.12,12345678.12);
$requestBody=new sendDataExtraccionRequest( (object)$array_datos );
Also tried a solution that involved json encoding and decoding the array, but same error
Any hint on how to achieve it?
Thanks
Use Spread Operator like this
$requestBody=new sendDataExtraccionRequest(...$array_datos);

Create an array of objects and then fetch object without losing their class

I'm trying to do some experiments with arrays and objects to improve my PHP programming basics.
What I would like to do is to save a collection of objects instantiated by one of my classes in a text file to be able to fetch them later.
My current implementation is to save the objects in an array, encode the array and save it to a JSON file.
However, the problem that arises is that when I then go to extract the objects these are no longer objects deriving from my class but are transformed into stdClass objects.
Here is the method I use to save objects to the file:
public function store(string $titolo, string $nomeAutore, string $titoloToDoList): void
{
FileChecker::FindOrBuild('Data/Tasks.json', "[]");
$newTask = new Task($titolo, $nomeAutore, $titoloToDoList);
$file = file_get_contents('Data/Tasks.json');
$decodedFile = json_decode($file);
array_push($decodedFile, $newTask->toArray());
file_put_contents('Data/Tasks.json', json_encode($decodedFile));
FileChecker::FindOrBuild('log/log.txt', "Logs: \n");
Logger::logTaskStore($nomeAutore, $titoloToDoList);
}
and then I extract from the file with a simple json_decode ()
Can anyone suggest some alternative method to save objects in a text file without losing the class?
edit:
forgot to put the toArray() code which is simply
public function toArray(): array
{
return get_object_vars($this);
}
There are as many file formats as there are people who need to store something slightly different in a file. It's up to you to figure out which one makes sense for your application.
JSON is a file format designed to be very simple and flexible, and portable between lots of different languages. It has no concept of "class" or "custom type", and its "object" type is just a list of key-value pairs. (Have a look at the file your current code creates, and you'll see for yourself.)
You can build a file format "on top of" JSON: that is, rather than storing your objects directly, you first build a custom structure with a way of recording the class name, perhaps as a special key on each object called "__class". Then to decode, you first decode the JSON, then loop through creating objects based on the name you recorded.
You mentioned in comments PHP's built-in serialize method. That can be a good choice when you want to store full PHP data for internal use within a program, and will happily store your array of objects without extra code.
In both cases, be aware of the security implications if anyone can edit the serialized data and specify names of classes you don't want them to create. The unserialize function has an option to list the expected class names, to avoid this, but may have other security problems because of its flexibility.

Instantiate an stdClass object from json schema specification in PHP

I have a set of JSON requests that I must send to a RESTFul API in order to get some response objects, you know, the usual thing for a webapp, however these API request objects are properly documented with a json schema specification for each, so I would like to load those schema files and create stdClass object instances based on that info automagically.
Is there some way to do this with a library or something in PHP? (don't want to reinvent the wheel)
Thanks!
Edit: Have a look at this schema file which contains an example of what I want to load and build object instances from.
Disclaimer: I do know json_encode / json_decode which is not what I'm looking for. Using that I'd need to traverse through the returned schema object and then create another object/array based on the schema read, which is not what I want.
I don't think there's a built-in way of doing this, but it should be relatively trivial to implement:
function createObj( $json ) {
$obj_schema = json_decode($json, true);
$new_obj = new StdClass;
foreach($obj_schema['properties'] as $property) {
$new_obj->{$property} = null;
}
return $new_obj;
}

saving parts of xml object as object

I created an xml file that stores some information for me. Now I want to get elements that meet some conditions.
At the moment this looks like this:
Function getElements($xmlObject, $name){
foreach($xmlObject->feature as $feature){
if(stristr($feature->path, $name))){
array_push($aSubFeatures, $feature);
}
}
return $obj;
}
But I'd prefer getting an object as a return value. I used simpleXML for getting the xml file as an object.
I also tried using DOM (creating new DOMDocument and tried to append the gotten feature element objects) but without reasonable result.
Would deleting all not matching parts of the xml a solution? Did not found a way to delete special elements...
Thanks for your help
For appending an element of a current existing DOMDocument into a new DOMDocument you have to call $newdom->importNode($nodeInOldDOM). You cannot do a regular appendChild of a node from another document.

PHP Web Service - Same call: Multiple records = array, 1 record=single object - How to work around?

I'm consuming a web service in PHP. If the service returns 2 or more records the object comes back as an array. However, if I call the same service that returns 1 record, the object is not an array. This makes for some messy logic having to watch for both cases when one would think PHP could be smart enough to handle this appropriately and always return an array of 1 element.
So my question is - is there a way to force the return object to always be an array? Some property in the call or something?
EDIT
I'm using PHP's soapclient library. The service is an in-house one that returns an array of a custom class.
you could try the following:
$client = new SoapClient("http://host/services/some.wsdl",
array('feature' => SOAP_SINGLE_ELEMENT_ARRAYS));
This should make php behave the way you want.
Also you might find this dotvoid article interesting.
HTH

Categories