php soapclient examples. Writing a SOAP client-server application in PHP
I need to connect to one web service and this is all I have:
Call example:
I know this function returns a string;
This is what I have done so far:
Created a Service Reference adding only the WSDL address specified in point 1.
Created a webservice instance and called the function with all the required parameter but no user and password for the header.
How can I continue? Thank you in advance.
1 answer
This might be a good place to start if you need to add your credentials; i think you might have to since you got them somehow. The part where you add your credentials is listed below:
UsernameToken userToken = new UsernameToken(userName, password, PasswordOption.SendHashed); Service1 serviceProxy = new Service1(); SoapContext requestContext = serviceProxy.RequestSoapContext; requestContext.Security.Tokens.Add(userToken);
- Add your credentials by inserting them into a specific token - the type of which belongs to the Microsoft.Web.Services2.Security.Tokens namespace
- Create a proxy for your service (in the above example, serviceProxy)
- Access your request header through your RequestSoapContext service
- Add token to request
Also, I think you could skip the "?wsdl" part of the address as it refers to the web service specification. Once that's done, you can try calling the function and see how it all pans out: if the function should return something, check what you expected.
I'm used to writing PHP code, but don't use object oriented coding much. Now I need to interact with SOAP (as a client) and I can't seem to get the syntax right. I have a WSDL file which allows me to properly set up a new connection using the SoapClient class. However, I can't make the right call and get the data back. I need to send the following (simplified) data:
- contact ID
- contact name
- general description
- Sum
There are two functions in the WSDL document, but I only need one ("FirstFunction" below). Here is the script I am running to get information about available functions and types:
$client = new SoapClient("http://example.com/webservices?wsdl"); var_dump($client->__getFunctions()); var_dump($client->__getTypes());
And here is the output it generates:
Array( => "FirstFunction Function1(FirstFunction $parameters)", => "SecondFunction Function2(SecondFunction $parameters)",); array( => struct Contact ( id id; name name; ) => string "string description" => string "int amount" )
Suppose I want to call FirstFunction with data:
- Contact ID: 100
- Contact person: John
- General Description: Barrel of Oil
- Amount: 500
What would be the correct syntax? I've tried all sorts of variations, but the soap structure seems to be quite flexible, so there are so many ways to do it. Couldn't figure it out from the manual...
UPDATE 1: Tried sample from MMK:
$client = new SoapClient("http://example.com/webservices?wsdl"); $params = array("id" => 100, "name" => "John", "description" => "Barrel of Oil", "amount" => 500,); $response = $client->__soapCall("Function1", array($params));
But I get this response: Object has no "Contact" property . As you can see in the output of getTypes() , there is a struct called Contact , so I think I somehow need to clarify that my parameters include Contact data, but the question is: how?
UPDATE 2: I also tried these structures, same error.
$params = array(array("id" => 100, "name" => "John",), "Barrel of Oil", 500,);
As well as:
$params = array("Contact" => array("id" => 100, "name" => "John",), "description" => "Barrel of Oil", "amount" => 500,);
Error in both cases: Object does not have "Contact" property
8 responses
This is what you need to do.
Just to know, I tried to recreate your situation...
- In this example, I have created a .NET web service using a WebMethod called Function1 and these are the parameters:
Function1 (contact pin, string description, int count)
In which Contact is just a bean class that has getters and setters for id and name , like in your case.
You can download this .NET web service with:
The code.
This is what you need to do on the side PHP:
(Tested and working)
id = $id; $this->name = $name; ) ) /* Initialize webservice with your WSDL */ $client = new SoapClient("http://localhost:10139/Service1.asmx?wsdl"); /* Fill your Contact Object */ $contact = new Contact(100, "John"); /* Set your parameters for the request */ $params = array("Contact" => $contact, "description" => "Barrel of Oil", "amount" => 500,); /* Invoke webservice method with your parameters, in this case: Function1 */ $response = $client->__soapCall("Function1", array($params)); /* Print webservice response */ var_dump($response); ?>
How do I know it's working?
- If you do print_r($params); , you will see this output as your web service is expecting:
Array ([Contact] => Contact object ( => 100 => John) [description] => Oil barrel [amount] => 500)
- When I debugged the sample .NET webservice I got the following:
(As you can see, the Contact object is not null, as well as other parameters, which means that your request was successfully completed from the PHP side).
- The response from the .NET webservice was as expected and shown on the PHP side:
object (stdClass) public "Function1Result" => string "Details for your request! id: 100, name: John, description: Barrel of oil, quantity: 500" (length = 98)
Hope this helps :-)
You can also use SOAP services:
"Spain", "CityName" => "Alicante"); $response = $soapclient->getWeather($params); var_dump($response); // Get the Cities By Country $param = array("CountryName" => "Spain"); $response = $soapclient->getCitiesByCountry($param); var_dump($response);
This is an example with a real service and it works.
Hope this helps.
First, initialize the web services:
$client = new SoapClient("http://example.com/webservices?wsdl");
Then set and pass parameters:
$params = array ("arg0" => $contactid, "arg1" => $desc, "arg2" => $contactname); $response = $client->__soapCall("methodname", array($params));
Note that the method name is available in the WSDL as the name of the operation, for example:
I don't know why my web service has the same structure as yours, but it doesn't need a class for the parameter, just an array.
For example:- My WSDL:
Var_dump($client->getFunctions()); var_dump($client->getTypes());
Here is the result:
Array 0 => string "OrderConfirmation createOrder(OrderRequest $createOrder)" (length=56) array 0 => string "struct OrderRequest ( Identification identification; Delivery delivery; Parcel parcel; Receiver receiver; string reference; )" (length=130) 1 => string "struct Identification ( string sender; string hash; string originator; )" (length=75) 2 => string "struct Delivery ( Node from; Node to; )" (length=41) 3 => string " struct Node ( string country; string node; )" (length=46) 4 => string "struct Parcel ( string description; decimal weight; string orderNumber; date orderDate; )" (length=93) 5 => string "struct Receiver ( string firstName; string surname; Address address; string email; string language; )" (length=106) 6 => string "struct Address ( string line1; string line2; string postalCode; string city; string country; )" (length =99) 7 => string "struct OrderConfirmation ( string trackingNumber; string reference; )" (length=71) 8 => string "str uctOrderServiceException(stringcode; OrderServiceException faultInfo; string message; )" (length=97)
So in my code:
$client = new SoapClient("http://packandship-ws.kiala.com/psws/order?wsdl"); $params = array("reference" => $orderId, "identification" => array("sender" => param("kiala", "sender_id"), "hash" => hash("sha512", $orderId . param("kiala", "sender_id") .param("kiala", "password")), "originator" => null,), "delivery" => array("from" => array("country" = > "es", "node" => "",), "to" => array("country" => "es", "node" => "0299")),), "parcel" => array( "description" => "Description", "weight" => 0.200, "orderNumber" => $orderId, "orderDate" => date("Ymd")), "receiver" => array("firstName" => " Customer First Name", "surname" => "Customer Sur Name", "address" => array("line1" => "Line 1 Adress", "line2" => "Line 2 Adress", "postalCode" => 28006, "city" => "Madrid", "country" => "es",), "email" => " [email protected]", "language" => "es")); $result = $client->createOrder($params); var_dump($result);
but he is successful!
This is a good example for the SOAP "__call" function. However, it is outdated.
Envio Internacional: "; $vem = $cliente->__call("CustoEMSInternacional",array($int_zona, $int_peso)); print $vem; print "
"; ?>SOAP (Simple Object Access Protocol) is an XML-based protocol for exchanging structured information between distributed applications over existing web protocols such as HTTP. The SOAP specification defines the format used by XML messages, how they should be handled by a set of encoding rules for the standard, data types, and conventions for remote procedure calls and call responses.
Web services are a trendy and modern technology. The list of technologies related to web services is growing almost daily, but SOAP is probably the most important of them all. It is rapidly becoming the standard protocol for accessing web services. It uses XML messages to exchange information between endpoints while providing some of the benefits of binary protocols. Support for RPC (Remote Procedure Calls) was one of the minor features of the SOAP protocol in the beginning, but now it has become one of the most used features.
The SOAP extension for PHP 5 is the first attempt to implement SOAP support in PHP in C. It has several advantages over existing SOAP implementations written in PHP, the most important of which is speed. At the moment, the extension is considered experimental, but gradually it will become more and more reliable and stable.
The SOAP extension implements large subsets of the SOAP 1.1, SOAP 1.2, and WSDL 1.1 specifications. The main goal is to make the most of SOAP's RPC capabilities. Wherever possible, WSDL is used to make the implementation of web services easier.
First SOAP client
To demonstrate how to create a simple SOAP client, we use the "Delayed Stock Quote" demo service from the XMethods site. Before we start writing PHP code, we need to collect the following information about this particular service:
- Method name
- The URL where this service is located
- The value of the SOAPAction method header
- Method namespace
- Names and types of method input and output parameters
Fortunately, all this information is available on the XMethods website at http://www.xmethods.com/ from the service's RPC profile:
Method name | getQuote |
Service URL | http://66.28.98.121:9090/soap |
SOAPAction | urn:xmethods-delayed-quotes#getQuote |
Method namespace | urn:xmethods-delayed-quotes |
Input parameters | Symbol (String) |
output parameters | result (float) |
Example 1 (client1.php)
$client = new SoapClient(NULL ,
array(
"location" => "http://66.28.98.121:9090/soap",
"uri" =>
"style" => SOAP_RPC ,
"use" => SOAP_ENCODED
));
Print($client -> __call(
/* SOAP method name */
"getQuote" ,
/* Parameters */
array(
new SoapParam(
/* Parameter value */
"ibm" ,
/* Parameter name */
"symbol"
)),
/* Options */
array(
/* SOAP method namespace */
"uri" => "urn:xmethods-delayed-quotes" ,
/* SOAPAction HTTP header for SOAP method */
"soap action" => "urn:xmethods-delayed-quotes#getQuote"
)). "\n");
?>
As you can see, solving this simple problem required quite a lot of work.
Fortunately, web services can describe themselves to clients using WSDL, which is generally quite convenient. The WSDL for the "Delayed Stock Quote" service is available on its info page on xmethods.com - http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl .
Here is a version of the same client rewritten to work with this WSDL document. Here we no longer need to specify the server URI, namespace, SOAPAction header, encoding method, and parameter types. All this information is taken from the WSDL file.
Example 2 (client2.php)
$client = new
SoapClient(
"http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl"
);
Print($client -> getQuote("ibm" ));
?>
That's a little easier, right?
What problems arise when using WSDL? The only argument against using it is that the client must read the WSDL from the server before any procedure can be called, which can take quite a long time on the web. To speed things up, the SOAP extension provides the following configuration options: soap.wsdl_cache_enabled, soap.wsdl_cache_dir and soap.wsdl_cache_ttl. They can be set in the php.ini file or with ini_set() (see Example 4). By default, WSDL caching is enabled and WSDL files are cached for 1 day.
Here is the SOAP section of the php.ini file with the default values. You can copy them to your php.ini.
[soap]
soap. wsdl_cache_enabled = "1"
;
enable or disable WSDL caching
soap. wsdl_cache_dir = "/tmp"
;
specifies the name of the directory in which the SOAP-
extension will store cached files
soap. wsdl_cache_ttl="86400"
; (lifetime ) sets the time(in seconds) which files from the cache can be used
First SOAP Server
Let's try to write our own SOAP web service that will do the same as the "Delayed Stock Quote" service with XMethods.
The first thing to do is create a WSDL document that describes our service in a format that clients can understand. To do this, you will need to slightly modify the original document taken from the Xmethods website, so we will start by looking at it in more detail.
The message section defines two messages. The first is getQuoteRequest , which sends a message to getQuote and takes a single-string parameter named symbol. The second message is getQuoteResponse, the response to the getQuote request, passing a single float value named Result.
The portType section defines a single getQuote operation that specifies which of the messages described in the message section will be used for the request and which for the response.
The binding section defines how the message is to be encoded and transmitted. In this case, it says that we will send the RPC request over HTTP using SOAP encoding. It also defines the namespace and value of the SOAPAction header for the getQuote method.
Finally, the service section defines the URL where the service is located.
Example 3 (stockquote.wsdl)
xmlns:tns="http://example.org/StockQuote"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
Note: WSDL caching is enabled by default. While developing and debugging your WSDL, caching is best disabled.
Now it's time to start creating our server.
First of all, we will develop a getQuote() function that will process incoming requests from the web. Next, we will create an object of the SoapServer class and attach our function to it using the SoapServer::addFunction() method. As you will see later, the SoapServer() constructor has only one parameter - the path to the WSDL document that describes the service.
Example 4 (server1.php)
$quotes = array(
"ibm" => 98.42
);
global $quotes ;
return $quotes [ $symbol ];
}
ini_set("soap.wsdl_cache_enabled" , "0" ); // disable WSDL caching
$server = new SoapServer("stockquote1.wsdl" );
$server -> addFunction("getQuote");
$server -> handle();
?>
SoapServer can work without WSDL, much like a client, but this option does not have any advantages that would make it worth using. If you still want to work this way, you must make sure that the return values are objects of the SoapParam and SoapVar classes (as in the first example.
Here is the client to access our SOAP server. Compared to the previous example, only a link to the location of the WSDL has been added. The file "stockquote1.wsdl" is supposed to be in the same directory as the SOAP server.
Example 5 (client3.php)
$client = new SoapClient("stockquote1.wsdl" );
print($client -> getQuote("ibm" ));
?>
What are the main problems in our client and server?
For starters, they don't handle errors. What happens when the server does not find a suitable result for the symbol value passed to it? SOAP has a special message format for error messages, SoapFault. To generate such a message, the server must throw an exception using the SoapFault object. The first parameter of the SoapFault() constructor is a string with the error code, the second is a string with a description of the error. The client must be written to handle SoapFault exceptions.
Secondly, the web service functionality is best encapsulated in a PHP class. In this case, we will not need to use global variables and add each SOAP method to the server separately. Instead, we can add an entire class, and all of its methods will be available via SOAP. Here are the client and server versions modified accordingly.
Example 6 (server2.php)
class QuoteService(
private $quotes = array("ibm" => 98.42 );
Function getQuote ($symbol ) (
if (isset($this -> quotes [ $symbol ])) (
return $this -> quotes [ $symbol ];
) else (
throw new SoapFault("Server" , "Unknown Symbol "$symbol"." );
}
}
}
$server = new SoapServer("stockquote2.wsdl" );
$server -> setClass("QuoteService");
$server -> handle();
?>
As you can see, I used the SoapServer::setClass() method to connect the SoapServer object to the QuoteService class.
Example 7 (client4.php)
$client = new SoapClient("stockquote2.wsdl");
try(
echo "
\n" ;\n" ;
print($client -> getQuote("ibm" ));
echo "\n" ;
print($client -> getQuote("microsoft" ));
echo "\n
) catch (SoapFault $exception ) (
echo $exception ;
}
?>
What's inside?
If you want to understand the format of SOAP messages, or want to debug a SOAP client yourself, then this section is for you.
As you saw in the first example, the SoapClient() constructor takes an associative array as its second parameter. With this array, we can call various options on the server.
Let's see two of them:
- trace - allows the client to store SOAP requests and responses (off by default).
- exceptions - allows the client to control the exception mechanism (enabled by default).
Let's look at the following SOAP client example. This is a modified client from Example 5, showing exactly what is passed between the client and the server. To obtain this information, the __getLastRequest() and __getLastResponse() methods are used.
Example 8 (client5.php)
$client = new SoapClient("stockquote1.wsdl" ,array(
"trace" => 1 ,
"exceptions" => 0 ));
$client -> getQuote("ibm" );
print"
\n" ;" ;
print "Request:\n" . htmlspecialchars ($client -> __getLastRequest()) . "\n" ;
print "Answer:\n" . htmlspecialchars($client -> __getLastResponse()). "\n" ;
print"
?>
Here is the output of the script. It has been slightly modified to make it easier to understand.
Inquiry:
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
Answer:
xmlns:ns1="urn:xmethods-delayed-quotes"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
Other SOAP implementations for PHP
They are all written in PHP, not C.
Summary
In this article, I have only described the main features of the SOAP extension. In fact, it can do much more, but it is simply impossible to demonstrate all its capabilities within the framework of one short article. Here is a list of the main ones:
- Support for complex data types (arrays, objects)
- Support for SOAP - headers
- Dynamic support for SOAP 1.1 and SOAP 1.2
Perhaps they will be discussed in more detail in future articles.
Detailed documentation for the SOAP extension is located at http://www.php.net/manual/en/ref.soap.php .
The development of this extension is in its early stages, so your feedback will help make it more stable, reliable, user-friendly and faster. Please report any problems you encounter while using it at http://bugs.php.net/ .
Links
about the author
To create a SOAP web service in PHP, you first need to install and configure PHP, as well as a local HTTP server. In this project, the XAMP package was used, which allows for a quick installation of the Apache HTTP server and PHP.
Separately, you need to make changes to the Apache and PHP configuration files.
In the configuration file of the Apache HTTP server httpd.conf, you need to find the following code snippet:
To run PHP scripts on a local server, you need to store them in the root directory of the Apache server, by default, the htdocs folder in the Apache root folder.
To change the root directory of the site, you need to make changes to the httpd.conf file in the line below:
To enable PHP support, the following lines must be added to the httpd.conf file:
To start the Apache HTTP server, you can use console commands, or the XAMMP control panel, which allows you to manage the state of Apache, as well as configure it.
The view of this utility is shown in Figure 2.
Figure 2. - XAMMP Control Panel utility:
To create a SOAP web service, you need to write PHP documents that implement the client and server sides of the application, as well as a WSDL page to describe the web service.
Let's create a web service that provides a single web service that returns to the client the result of performing an arithmetic operation on two numbers. The input elements are two numbers specified by the client, as well as a character variable that defines the arithmetic operation.
The client side is implemented by two PHP documents. In the form.php file using the element