PHP SOAP Extension PHP SOAP Extension - Heliguy

therapistarmySoftware and s/w Development

Dec 14, 2013 (3 years and 10 months ago)

78 views

ZEND Developers zone
PHP SOAP Extension
http://devzone.zend.com/node/view/id/689
PHP SOAP Extension
Advanced



SOAP



Tutorials



XML



by
Dmitry Stogov
|
9 comments
| Tuesday, March 16, 2004
Intended Audience
Introduction
A First SOAP Client



Example 1 (client1.php)



Example 2 (client2.php)



A First SOAP Server



Example 3 (stockquote.wsdl)



Example 4 (server1. php)



Example 5 (client3.php)



Example 6 (server2.php)



Example 7 (client4.php)
What's inside?



Example 8 (client5.php)
Other Implementations of SOAP for PHP
Summary
References
About the Author
Revision Date
Intended Audience
This article describes the new SOAP extension for PHP. It is intended for PHP developers who want

to write their own Web Services servers, or use SOAP to access existing ones. It assumes some

familiarity with Web Services, SOAP, and WSDL (Web Services Description Language).
Introduction
SOAP (Simple Object Access Protocol) is a lightweight XML-based protocol for exchanging

structured information between distributed applications over native web protocols, such as HTTP.

ZEND PHP SOAP
6.4.2007
08:33:32
Strana
1
ze
14
SOAP specifies the formats that XML messages should use, the way in which they should be

processed, a set of encoding rules for standard and application-defined data types, and a convention

for representing remote procedure calls and responses.
Web Services is a modern and very popular technology. The list of protocols and technologies

related to Web Services grows every day, but SOAP is probably the most important. It is rapidly

becoming the standard protocol for accessing Web Services. It uses XML messages to exchange

information across endpoints, and provides several advantages over other binary protocols. RPC

(Remote Procedure Calls) support was originally a minor element in the design of SOAP, but this

feature is one of the most useful it has today.
PHP 5's SOAP extension is the first attempt to implement the SOAP protocol for PHP in C. It has

some advantages over the existing implementations written in PHP itself, the main one being speed.

The extension is currently marked as experimental, but should gradually become more stable and

reliable as time progresses.
The SOAP extension implements a large subset of SOAP 1.1, SOAP 1.2 and WSDL 1.1

specifications. The key goal is to use the RPC feature of the SOAP protocol. WSDL is used where

possible in order to make the implementation of Web Services more straightforward.
A First SOAP Client
To demonstrate how to make a simple SOAP Client, we'll take the XMethods demo service,

“Delayed Stock Quote”, as our target. Before we start to write any PHP code, we'll need to gather

some information about this particular service:

The method name

The endpoint URL where the service is running

The SOAPAction header value for the method

The namespace URI for the method

Input and output parameter names and types
Happily, all this information is available on the XMethods web site at
http://www.xmethods.com/
in

the form of the service's RPC profile:
Method Name
getQuote
Endpoint URL
http://64.124.140.30:9090/soap
SOAPAction
urn:xmethods-delayed-quotes#getQuote
Method

Namespace URI
urn:xmethods-delayed-quotes
Input

Parameters
Symbol
String
Output

Parameters
Result
float
Example 1 (client1.php)
<?php
ZEND PHP SOAP
6.4.2007
08:33:32
Strana
2
ze
14
$client = new SoapClient(NULL,








array(








"location" => "http://64.124.140.30:9090/soap",








"uri"






=> "urn:xmethods-delayed-quotes",








"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 */












"soapaction" => "urn:xmethods-delayed-quotes#getQuote"









)). "\n");
?>
As you can see, this simple task required a lot of work
Fortunately, Web Services can describe themselves to the client using WSDL, and generally they

achieve this successfully. The location of the WSDL document for the XMethods “Delayed Stock

Quote” service is given on the information page for that service at xmethods.com:
http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl

Here is the same PHP SOAP client, rewritten using that WSDL document. Now we don't need to

specify the endpoint URI, namespace, SOAPAction header, encoding style and parameter types. All

the information comes from the WSDL file.
Example 2 (client2.php)
<?php
$client = new




SoapClient(








"http://services.xmethods.net/soap/urn:xmethods-delayed-
quotes.wsdl"




);
print($client->getQuote("ibm"));
ZEND PHP SOAP
6.4.2007
08:33:32
Strana
3
ze
14
?>
That's a little easier, isn't it?
What are the problems with WSDL? The only argument against using it is that the client has to load

the relevant WSDL document from the server before the RPC can be made, and this can take a

significant amount of time in a Web environment. In order to speed things up, PHP's ext/soap uses a

WSDL caching feature that can be controlled through setting the

soap.wsdl_cache_enabled, soap.wsdl_cache_dir
and
soap.wsdl_cache_ttl

configuration directives, either in your php.ini or by using
ini_set()
(see Example 4 ). By

default, WSDL caching is turned on and caches WSDL files for one day.
Here is the SOAP section for php.ini with default values. You can paste it into your php.ini.
[soap]
soap.wsdl_cache_enabled = "1"
; enables or disables WSDL caching feature
soap.wsdl_cache_dir = "/tmp"
; sets the directory name where SOAP extension will put cache

files
soap.wsdl_cache_ttl = "86400"
; (time to live) sets the number of second while cached file will

be used
; instead of original one
A First SOAP Server
Let's try to write our own SOAP Web service that will do the same as the XMethods “Delayed

Stock Quote” service.
The first task is to create a WSDL document describing our service in a format that client requests

will understand. This requires minor modifications to the original document taken from the

Xmethods site, so we'll start by taking a close look at that file.
The
message
section defines two messages. The first is
getQuoteRequest
, which is a request

to relay the
getQuote
message and takes one string parameter called
symbol.
The other is

getQuoteResponse
, which is a response to the
getQuote
message, containing one float

value, named
Result
.
The
portType
section defines one operation,
getQuote
,
which describes which of the messages

listed in the
message
section will be used to transmit the request and response.
The
binding
section defines how the messages must be transmitted and encoded. Here it tells us

that we will be sending an RPC request using SOAP encoding across HTTP. It also specifies

namespace and value of the SOAPAction header for the
getQuote
method.
Lastly, the
service
section defines the endpoint URL where the service is running.
ZEND PHP SOAP
6.4.2007
08:33:32
Strana
4
ze
14
Example 3 (stockquote.wsdl)
<?xml version ='1.0' encoding ='UTF-8' ?>
<definitions name='StockQuote'


targetNamespace='http://example.org/StockQuote'


xmlns:tns=' http://example.org/StockQuote '


xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'


xmlns:xsd='http://www.w3.org/2001/XMLSchema'


xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/'


xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'


xmlns='http://schemas.xmlsoap.org/wsdl/'>
<message name='getQuoteRequest'>


<part name='symbol' type='xsd:string'/>
</message>
<message name='getQuoteResponse'>


<part name='Result' type='xsd:float'/>
</message>
<portType name='StockQuotePortType'>


<operation name='getQuote'>




<input message='tns:getQuoteRequest'/>




<output message='tns:getQuoteResponse'/>


</operation>
</portType>
<binding name='StockQuoteBinding' type='tns:StockQuotePortType'>


<soap:binding style='rpc'




transport='http://schemas.xmlsoap.org/soap/http'/>


<operation name='getQuote'>




<soap:operation soapAction='urn:xmethods-delayed-
quotes#getQuote'/>




<input>






<soap:body use='encoded' namespace='urn:xmethods-delayed-
quotes'








encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/
>




</input>




<output>






<soap:body use='encoded' namespace='urn:xmethods-delayed-
quotes'








encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/
>




</output>


</operation>
</binding>
<service name='StockQuoteService'>


<port name='StockQuotePort' binding='StockQuoteBinding'>




<soap:address location='http://[insert real path

here]/server1.php'/>
ZEND PHP SOAP
6.4.2007
08:33:32
Strana
5
ze
14


</port>
</service>
</definitions>
Note: The WSDL caching feature is on by default. During the development of your WSDL file it

should be turned off.

Now it's time to create our server.
First, we'll implement the
getQuote()
function, which will be accessed as a service function by

incoming request messages from the web. Next, we'll create a
SoapServer
object and connect it

with the service function using
SoapServer::addFunction()
method. As you will see, the

SoapServer()
constructor has only one parameter: the path of the WSDL document that

describes the service.
Example 4 (server1. php)
<?php
$quotes = array(


"ibm" => 98.42
);



function getQuote($symbol) {


global $quotes;


return $quotes[$symbol];
}
ini_set
("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache
$server = new SoapServer("stockquote.wsdl");
$server->addFunction("getQuote");
$server->handle();
?>
The
SoapServer
can work without a WSDL document in much the same way that the

SoapClient
can, but there are no obvious benefits to be had from setting it up in this way. Were

you to do so, you should ensure that the return values are special objects of the
SoapParam
and

SoapVar
classes (as in the first example).
Here is a client for accessing our own SOAP server. Nothing has changed from the previous

example except the WSDL location. It assumes that “stockquote.wsdl” is in the same directory as

our SOAP server.
Example 5 (client3.php)
<?php


$client = new SoapClient("stockquote.wsdl");


print($client->getQuote("ibm"));
?>
What are the problem areas with our server and client?
To start with, they don't handle errors. What happens when the server doesn't recognize the

ZEND PHP SOAP
6.4.2007
08:33:32
Strana
6
ze
14
requested symbol? The SOAP protocol specifies a special format of messages for reporting errors

� SoapFault. To generate such messages the server should throw an exception using the

SoapFault
object. The first parameter to the
SoapFault()
constructor is a fault code string,

and the second is a fault description string. The client should be written in such a way as to catch

SoapFault exceptions.
Secondly, it would be better to encapsulate Web Service functionality in a PHP class. In this case we

wouldn't need to use global variables and add each SOAP method to the server individually; we

could add an entire class, and all its methods would be accessible through SOAP.
Save
stockquote.wsdl
as
stockquote2.wsdl
, and alter the
soap:address
on line 43

to point to
server2.php
. A modified version of our SOAP server and client follows:
Example 6 (server2.php)
<?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 have used the
SoapServer::setClass()
method to connect the SoapServer

object with the QuoteService class.
Example 7 (client4.php)
<?php


$client = new SoapClient("stockquote2.wsdl");


try {




echo "<pre>\n";




print($client->getQuote("ibm"));




echo "\n";




print($client->getQuote("microsoft"));







echo "\n</pre>\n";


} catch (SoapFault $exception) {




echo $exception;









}
?>
ZEND PHP SOAP
6.4.2007
08:33:32
Strana
7
ze
14
What's inside?
Are you curious about the SOAP message format, or hoping to debug a SOAP client of your own?

If so, this section is for you.
The
SoapClient()
constructor accepts an associative array as its second parameter, as you

already saw in the first example. Various options can be passed through this associative array. Here

are just two:

trace
– allows the client to store SOAP requests and responses (turned off by default)

exceptions
– allows the client to control the exception mechanism (turned on by default)

Take a look at the following SOAP client example. It is derived from example 5, and shows

precisely what is transmitted between the client and the server. In order to retrieve this information

we use the
SoapClient
methods
__getLastRequest()
and
__getLastResponse()
.
Example 8 (client5.php)
<?php


$client = new SoapClient("stockquote.wsdl",array(




"trace"






=> 1,




"exceptions" => 0));


$client->getQuote("ibm");


print "<pre>\n";


print "Request :\n".
htmlspecialchars
($client-
>__getLastRequest()) ."\n";


print "Response:\n".
htmlspecialchars
($client-
>__getLastResponse())."\n";


print "</pre>";
?>
Here is the output of the script. It is modified a little, to make it more easily understood.
Request :
<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope


xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"


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/">
<SOAP-ENV:Body>


<ns1:getQuote>




<symbol xsi:type="xsd:string">ibm</symbol>


</ns1:getQuote>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Response:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
ZEND PHP SOAP
6.4.2007
08:33:32
Strana
8
ze
14


xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"


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/">
<SOAP-ENV:Body>


<ns1:getQuoteResponse>




<Result xsi:type="xsd:float">98.42</Result>


</ns1:getQuoteResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Other Implementations of SOAP for PHP

PEAR::SOAP (
http://pear.php.net
)

NuSOAP (
http://dietrich.ganx4.com/nusoap
)

eZ SOAP (
http://ez.no
)
All the above are written in PHP, rather than in C.
Summary
In this article I have described only the basic functionality of the SOAP extension for PHP. In

reality it can do significantly more, but it isn't possible to demonstrate all its features in a short

article. The main ones are:

support for complex types (arrays, objects)

support for SOAP headers

dynamic support for both SOAP 1.1 and SOAP 1.2
Perhaps these will be starting points for future articles.
The SOAP extension is fully documented at
http://www.php.net/manual/en/ref.soap.php
.
The extension is still in the early development phase, so your feedback will help to make it more

stable, reliable, usable and fast. Please report any problems you find at
http://bugs.php.net/
.
References
“Simple Object Access Protocol (SOAP) 1.1” (
http://www.w3.org/TR/2000/NOTE-SOAP-
20000508/
)
“SOAP 1.2 Part 0: Primer” (
http://www.w3.org/TR/2003/REC-soap12-part0-20030624/
)
“SOAP 1.2 Part 1: Messaging Framework" (
http://www.w3.org/TR/2003/REC-soap12-part1-
20030624/
)
"SOAP 1.2 Part 2: Adjuncts" (
http://www.w3.org/TR/2003/REC-soap12-part2-20030624
)
ZEND PHP SOAP
6.4.2007
08:33:32
Strana
9
ze
14
“Web Services Description Language (WSDL) 1.1” (
http://www.w3.org/TR/2001/NOTE-wsdl-
20010315
)
"XML Schema Part 1: Structures" (
http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/
)
"XML Schema Part 2: Datatypes" (
http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/
)
About the Author
Dmitry Stogov is one of the authors of PHP's SOAP extension. He has also written the PECL/perl

extension and Turck MMCache. He currently resides in St.Petersburg, Russia with his wife and one

child. Please feel free to post any comments or questions below, or send them to
dmitry@zend.com
.
Revision Date
This article was last revised on December 6th 2004 [sf]
Comments
Add Comment
Tuesday, October 31, 2006
UNCAUGHT SOAPFAULT EXCEPTION: [CLIENT] LOOKS LIKE WE GOT NO XML

DOCUMENT
8:56PM PST ·
stromsky
I was following this article to learn myself to prepare and use web services in my PHP5. Article

explains very clearly how to deal with all basics. Unfortunately client built using SoapClient class

work fine until you are not trying to connect web service build using PHP5 Soap extension. I tried

to connect many services written in different languages with no problems, but connecting my own

service in PHP5 returns exception "Uncaught SoapFault exception: [Client] looks like we got no

XML document".
First I thought, that my WSDL (working on other platforms) does not work for me in PHP5, but I

tried to check it using few WSDL validators and I found it OK.
Could anyone have an idea, where could be a problem? I`ve spent hours by googling Internet but

with no success ;(.
Thank you for any advice.
Sunday, November 5, 2006
RE: UNCAUGHT SOAPFAULT EXCEPTION: [CLIENT] LOOKS LIKE WE GOT NO XML

DOCUMENT
8:47AM PST ·
kroesjnov
I've just spend half my evening trying to solve this problem, and your not gonna believe the

solution...
Did you by any chance copy&paste the text from this website? I know I did.
Did you also copy two whitespaces along with the rest, now comfortably resting before your

ZEND PHP SOAP
6.4.2007
08:33:32
Strana
10
ze
14
'<?php'? I sure did.
Do your errors disappear as soon as you strip these two leading whitespaces (along with any trailing

whitespaces behind '?>' if they happen to excist) from your code? Yep, you guessed right, they did

here.
I guess there is a parser at work behind the curtains somewhere which is rather strict, perhaps a bit

to strict.
(Tested with: WAMP5 1.6.6 : with PHP 5.2.0)
Wednesday, November 8, 2006
STOCKQUOTE.WSDL : SERVICE -> PORT -> BINDING
7:16AM PST ·
kroesjnov
It seems an error found it's way to the article (as far as I can tell from the W3C WSDL 1.1

examples[1]).
When simplifying the W3C example[2] the 'tns' was lost in the port binding in the service section:
On this page:
<service name='StockQuoteService'>
<port name='StockQuotePort' binding='StockQuoteBinding'>
<soap:address location='http://[insert real path here]/server1.php'/>
</port>
</service>
Should be:
<service name='StockQuoteService'>
<port name='StockQuotePort' binding='tns:StockQuoteBinding'>
<soap:address location='http://[insert real path here]/server1.php'/>
</port>
</service>
I noticed this when I tried to consume the webservice with Flash 8 (the PHP example above didnt

have a problem with it).
I am not entirely sure if this is the fault of the author, or that Flash 8 is at fault. I *think* the parser

is now looking for 'StockQuoteBinding' in the xmlns by default and not the xmlns:tns, yet I cant

find where I've read about this behaviour, and the W3C specifications are not helping me either on

this (or perhaps I am overlooking it there).
Either way, it's perhaps usefull information to someone.
[1] http://www.w3.org/TR/wsdl#_services
[2] http://www.w3.org/TR/wsdl#_wsdl
Friday, December 8, 2006
I CAN'T DO, IT ERROR
9:09PM PST ·
dangkhoi
When i copy code in this page to make webservice, i have error HTTP_ROW_POST_DATA.
It can find HTTP_ROW_POST_DATA.
Why???
ZEND PHP SOAP
6.4.2007
08:33:32
Strana
11
ze
14
Help me, help me to do.
Thanks
Monday, January 1, 2007
EXTRACTING SOAP HEADERS SENT FROM CLIENTS
4:44PM PST ·
israelekpo
One of the deficiencies of the PHP5 SOAP extension is the inability to extract Headers sent from

the clients. I think the only way to do this will be to manually extract and process any headers

received from the clients by the server.
Another way to handle this, which is not exactly the right way to do it, would be to include the

validation or authentication data in the message as part of the parameters to the function called

instead of sending them as part of the header.
Sunday, February 4, 2007
RETURN > 1 VALUE
8:09AM PST ·
jimdelong
In the above example, 1 value is returned. Are 2 values returned as an array? Or how would that be

done?
Thursday, March 8, 2007
SOAP-ERROR: PARSING WSDL: COULDN'T LOAD FROM
2:38PM PST ·
ccochella
This is a great article.
But I am having a problem when it comes to crafting my own server/client with the example.
My server does not parse the WSDL file with error:
SOAP-ERROR: Parsing WSDL: Couldn't load from
I have validated the file at:
http://www.mgateway.com/php/wsdlValidator/home.php
And it is valid, but the server response always has an error because it will not parse the wsdl.
Please help.
Thanks,
Chris
Here it is:
<?xml version='1.0' encoding='UTF-8'?>
<definitions name='StockQuote' targetNamespace='http://example.org/StockQuote' xmlns:tns='

http://example.org/StockQuote ' xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'

xmlns:xsd='http://www.w3.org/2001/XMLSchema'

xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/'

xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/' xmlns='http://schemas.xmlsoap.org/wsdl/'>
<message name='getQuoteRequest'>
<part name='symbol' type='xsd:string'/>
</message>
ZEND PHP SOAP
6.4.2007
08:33:32
Strana
12
ze
14
<message name='getQuoteResponse'>
<part name='Result' type='xsd:float'/>
</message>
<portType name='StockQuotePortType'>
<operation name='getQuote'>
<input message='tns:getQuoteRequest'/>
<output message='tns:getQuoteResponse'/>
</operation>
</portType>
<binding name='StockQuoteBinding' type='tns:StockQuotePortType'>
<soap:binding style='rpc' transport='http://schemas.xmlsoap.org/soap/http'/>
<operation name='getQuote'>
<soap:operation soapAction='urn:xmethods-delayed-quotes#getQuote'/>
<input>
<soap:body use='encoded' namespace='urn:xmethods-delayed-quotes'

encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</input>
<output>
<soap:body use='encoded' namespace='urn:xmethods-delayed-quotes'

encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</output>
</operation>
</binding>
<service name='StockQuoteService'>
<port name='StockQuotePort' binding='StockQuoteBinding'>
<soap:address location='https://dev1.mysite.com/site/admin/soap_server.php'/>
</port>
</service>
</definitions>
Sunday, March 18, 2007
QUESTIONS
6:45AM PDT · Anonymous User [unregistered]
Hello,
about this:
$server = new Soapclient($wsdl [, $options]);
May you explian about all of options in this function?
I heard about keys,May you explain about them?
2-about example 2,May tell more about this:"The only argument against using it is that the client

has to load the relevant WSDL document from the server before the RPC can be made"
3-Example 4:May you explain about this: Were you to do so, you should ensure that the return

values are special objects of the SoapParam and SoapVar classes (as in the first example).
ZEND PHP SOAP
6.4.2007
08:33:32
Strana
13
ze
14
Soapvar? special object?
Thanks
Monday, March 19, 2007
CCOCHELLA,
1:01PM PDT ·
vizions
you have mistake in xml definition. Check the definition line and look for example.org and replace

it with your server and path.
-Vz-
ZEND PHP SOAP
6.4.2007
08:33:32
Strana
14
ze
14