consuming web service (for the first time) in php - php

It took me a while to get soap configured in php. Now I'm just trying to learn about it. I'm using the web service here to learn:
http://www.webservicex.net/WCF/ServiceDetails.aspx?SID=19
It says the WSDL is here:
http://www.webservicex.net/stockquote.asmx?wsdl
and this is my code:
$client = new SoapClient('http://www.webservicex.net/stockquote.asmx?wsdl');
$result = $client->getQuote("AAPL");
echo $result;
I'm getting an error saying "Object of class stdClass could not be converted to string". Now I realize that $result is an object, and I'm wondering how do I access data that the server populated? I tried to understand the WSDL but I'm getting nowhere. Is it supposed to be something like:
$result->price
? (That doesn't work by the way...)
Ideas?

When curious about datatypes from the soapserver, use the SoapClient->__getTypes() & SoapClient->__getFunctions() methods
If you return is still not clear, var_dump() your return and examine it.

Related

GraphQL query in PHP without libraries

Is it possible to convert an array or an object in PHP to a GraphQL query without importing a library?
I'm hoping for something that works like json_encode does for JSON.
e.g.
$array['products']['edges']['node']['handle'] = true;
$graphql = graphql_encode($array);
echo $graphql; // prints: {products(first: 10) { edges { node { handle }}}}
Maybe this would always be an oversimplification (e.g. I'm not quite sure how "(first: 10)" would be added to the array).
But I'm just looking for a simple way to start experimenting with GraphQL (and I don't have access to SSH or Composer on my shared hosting so it's not easy for me to add the right libraries).

A complex soap call using PHP

I've worked on this for about 4 hours and I am real close but just missing the mark – here is what xml needs to look like
<ws:Answer QuestionID="Q_CAM_ID" ws:Datatype="string">
<ws:Value>6838</ws:Value>
</ws:Answer>
Here is what I get
<ns1:Answer QuestionID="Q_CAM_ID">
<ns1:Value>6838</ns1:Value>
</ns1:Answer>
Using
$A1 = new StdClass();
$A1->QuestionID = 'Q_CAM_ID';
$A1->Value =6838;
No matter what I try I can’t get “ws:Datatype="string"” to appear. I believe the answer is the below or real similar
$A1 = new StdClass();
$A1->QuestionID = new StdClass();
$A1->QuestionID->QuestionID ='Q_CAM_ID';
$A1->QuestionID->DataType ='string';
$A1->Value =6838;
But what I keep getting is this error
Catchable fatal error Object of class stdClass could not be converted to string when the soap call is done. If anyone has a clue I would be most appreciative
The simliest way to do it is to use a WSDL to php generator as you'll only deal with PHP object that matches the requires types. Moreover, if you a good WSDL to php generator, you'll have PHP classes that are named as the elements.
You could use https://www.wsdltophp.com or https://github.com/mikaelcom/WsdlToPhp.
Maybe I'm missing something but if you need that XML why not just make it as a String, and then convert it to what you are trying to do? If you are not using a WSDL or SimpleXML, I would just do the following.
$xml =
'
<ws:Answer QuestionID="Q_CAM_ID" ws:Datatype="string">
<ws:Value>6838</ws:Value>
</ws:Answer>
';

Generating a client with Soap 1.2 in php

Could you tell me if there is a tool to generate a soap client with these requirements:
soap 1.2
the client is based on three different service (so 3 wsdl)
those services have shared types
I found out about:
http://php.net/manual/en/class.soapclient.php
and
http://www.php.net/manual/en/soapclient.soapclient.php
The thing I can't find out searching for it is especially the last two point.
Any help will be appreciated because I can't unserstand how to create it from different sources and how to call a specific service.
I can't test my solution as i don't have 2-3 web services running, but i think this solution will work (if i understood you correctly). Please if you can try it and let me know.
<?php
class wstest {
function __construct($url) {
$this->soapUrl = $url;
try{
$this->client = new SoapClient($this->soapUrl,array('login' => 'wsuser', 'password' => "some_password", "connection_timeout"=>30,'trace'=>true,'keep_alive'=>false,'features' => SOAP_SINGLE_ELEMENT_ARRAYS));
} catch (Exception $e) {
echo $e->getMessage();
}
}
};
$con = new wstest("http://firstwebservice.com/?wsdl");
$con2 = new wstest("http://secondwebservice.com/?wsdl");
$con3 = new wstest("http://thirdwebservice.com/?wsdl");
?>
I'm trying to figure out what you might want to do.
First: One WSDL === one Service === one SoapClient. You cannot mix two WSDL locations on the Soap client level, but depending on your application, might connect each services' results on a higher level.
So if you have three WSDL, then you must instantiate three SoapClient classes to be used. It's not like a single generic HTTP Client which can make requests to any existing webserver.
Second: Unless you provide a classmap to the SoapClient, the return value of any request is only a mixture of stdClass and array. There might be types defined in the WSDL, but PHP does not map them to anything unless you define it.
I would recommend using a classmap with your own defined classes that match the ComplexType definitions in the WSDL. There are some code generators to be googled that might do the job, but the Soap standard is complex, as is the definitionof WSDL, so you might end up doing work by hand.
You can perfectly live without a classmap if the data structures are small.
Third: If the three WSDL share data types, this will not affect PHP in any way. Since without classmap the responses are stdClass and Array, and the Request parameters can be the same, you won't get any benefit from this information.
If on the other hand you go the way of the classmap, I'd expect that the shared types will lead to the same classes generated, so you would also see on the PHP level that a ComplexType from Service A is identical to the ComplexType of Service B.

Zend_Soap_Client error calling ASP.net web service: '...not set to an instance of an object'

I'm trying to use Zend_Soap_Client to communicate with an ASP.net web service. Here's my client call:
$client = new Zend_Soap_Client(null, array(
'location' => 'http://example.com/service.asmx',
'uri' => 'http://example.com/'
));
$user = new UserDetail();
$result = $client->UserDetails($user);
However this always gives me the error:
System.NullReferenceException: Object reference not set to an instance of an object. at Service.UserDetails(UserDetail UserDetail)
some googling revealed that this is quite a common problem. The most common solution seemed to be to pass the parameters as an array, so I tried:
$result = $client->UserDetails(array('UserDetail' => $user));
but this gave the same error. I also tried passing the params as a stdClass object, nesting the array in another with 'params' as the key, and a few other things but the error is always the same.
I have the ASP code for the web service itself, the relevant method is:
public Result UserDetails(UserDetail UserDetail) {
[some stuff]
Hashtable ht = new Hashtable();
ht = UserDetail.GenerateData();
}
the error is caused by the GenerateData() call.
I assume the UserDetails method is getting null instead of my object as the parameter, but I'm not sure how I should be calling the method, or how I can debug this further. The majority of the Zend_Soap_Client examples I've found seem to be using WSDL, which this service is not; not sure if that is relevant. Any help appreciated!
I eventually solved this with:
$userDetails = new UserDetails();
$userDetails->UserDetail = $user;
$client->UserDetails($userDetails);
it seems ASP.net expects (and returns) params to be nested in an object/array with the same name as the method being called.
If you have any possibility to change the asp.net code I'd suggest you try an implementation of the method UserDetails without parameters just to make sure that code isn't broken.
I would then create a consumer-method in asp.net, debug the http-request and see how the userdetail-object is serialized/broken down in array form. Then it's "just" a matter of creating a similar http request from php.

Calling web service (SOAP) with PHP involving enums

I wish to call a web service, using SOAP, from PHP (using the included SOAP extension). The web service in question is http://www.webservicex.net/CurrencyConvertor.asmx
Now the Currency type is an enum, and I cannot figure out how to work with these in PHP in order to be able to call the 'ConversionRate' function. I know I have to do something with a class map, but I can only find limited and unhelpful information on this topic. Can anyone help? A working example maybe?
Thanks!!!!
The enum here only defines legitimate values, that is your data type is actually a string of one of those values.
Here's some psuedo-code to get you on your way:
$from_currency = "AFA";
$to_current = "ALL";
$soap_handler->ConversionRate($from_currency, $to_currency);
$exchange_rate = $soap_handler->response();

Categories