PHP SOAP Extension

November 30, -0001

Tutorials

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. 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

$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"));

?>

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.


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'/>

  </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 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;      

  }

?>



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

  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

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)

“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]

,

About Cal Evans

Many moons ago, at the tender age of 14, Cal touched his first computer. (We're using the term "computer" loosely here, it was a TRS-80 Model 1) Since then his life has never been the same. He graduated from TRS-80s to Commodores and eventually to IBM PC's. For the past 10 years Cal has worked with PHP and MySQL on Linux OSX, and when necessary, Windows. He has built on a variety of projects ranging in size from simple web pages to multi-million dollar web applications. When not banging his head on his monitor, attempting a blood sacrifice to get a particular piece of code working, he enjoys building and managing development teams using his widely imitated but never patented management style of "management by wandering around". Cal is currently based in Nashville, TN and is gainfully unemployed as the Chief Marketing Officer of Blue Parabola, LLC. Cal is happily married to wife 1.28, the lovely and talented Kathy. Together they have 2 kids who were both bright enough not to pursue a career in IT. Cal blogs at http://blog.calevans.com and is the founder and host of Day Camp 4 Developers

View all posts by Cal Evans

31 Responses to “PHP SOAP Extension”

  1. daniphp Says:

    In case of this error remove the TWO white spaces from the server.php file you created ( at the beginning ).

    Check all files ( client,server,wsdl for empty spaces in the beginning )

  2. sethinsd Says:

    Where you have
    <port name=’StockQuotePort’ binding=’StockQuoteBinding’>

    you should instead have
    <port name=’StockQuotePort’ binding=’tns:StockQuoteBinding’>

    Although php’s soap client will work with either, you will get invalid wsdl errors on many frameworks, and I think this may be causing some of the issues that people are having.

  3. hogsolo Says:

    Got the provided example to work in a subdir just fine. http://myserver.xxx/soap01/client3.php,
    but then if I made a change to the files to make a new methed, basically changing "getQuote" to "addQuote", it wont work in the subdir anymore.
    It will work fine from the doc root, ie http://myserver.xxx/client3.php.

    Some sort of path/name issue?
    tired all combination I could think of with no luck.

  4. svenmarley Says:

    I have copied the code and wsdl. I have found and fixed all the errors as shown in the discussions. Including, changing the soap:address line to my localhost server. (PHP 5.2.8 with SOAP enabled)

    My client always times out. I can see the wsdl loads from the client because I can see the functions, etc… But any call to the server times out after 30 seconds.

    Is there any way to even see if the server is CALLING the soap server?

    I’ve tried 3 other examples all with the same results. I presume it is something to do with my server, but I don’t know what it is and can’t find any help online.

    Thanks for any help.

  5. gbs1230 Says:

    Thanks for the tip on adding tracing to SOAP calls in Zend. Very useful.

  6. barazandeh Says:

    You only need to replace:
    http://insert real path here]/server1.php
    with real url to get working!

  7. grunichev Says:

    I’m using external services, few of them can be unavaible, I’d like to use it as
    try {
    $client = new soapclient($wsdl);
    }
    catch(Exception $e)
    {

    }
    or something else.

    So, I except potential unavaiblity of service, but can’t do anything, I always get fatal error
    Fatal error: SOAP-ERROR: Parsing WSDL: Couldn’t load from
    and code is stopped.

    Can I solve my problem and continue script if $wsdl is unavaible?

  8. _____anonymous_____ Says:

    123456789

  9. sushanthcs Says:

    How can I biuld SOAP service over HTTPS using php. Please give me the example for server program,client program and WSDL. and how can I build SOAP Server WSDL without using "http://schemas.xmlsoap.org/soap/&quot;

  10. ptlh2008 Says:

    I always get above error when run the client. Anybody has an idea?
    thanks. Looks like quite difficult to debug..

  11. ptlh2008 Says:

    I always get above error when run the client. Anybody has an idea?
    thanks. Looks like quite difficult to debug..

  12. _____anonymous_____ Says:

    If you get the SOAp error "Error cannot find parameter", make sure the wsdl of your server and client are the same.

    Espacially if you cnaged params of functions during development.

    When developing both the client and server should have:
    ini_set("soap.wsdl_cache_enabled", 0);

    If you (like me) have this setting only at either server or client, you might get the above error and waste alot of time tracking it.

  13. _____anonymous_____ Says:

    sorry not speaking English … very good tutorial
    i’m working on XP, localhost for testing

    for Anonymous User (Mark) : very simple
    copy :
    php_soap.dll from your php-5.x.x-Win32/ext instal Php ZIP file
    on :
    local : like ( C:\php\extensions\php_soap.dll )

    and verify php.ini on C:\windows ( search soap )

  14. _____anonymous_____ Says:

    I have been trying to get this example to work. I have turned on ‘always_populate_raw_post_data’, however, I am getting the following error:

    SoapFault exception: [SOAP-ENV:Server] Bad Request. Can’t find HTTP_RAW_POST_DATA

    I am using PHP 5.2.2

  15. _____anonymous_____ Says:

    Actually trying to follow this tutorial to get Soap going but it just keeps giving me the "HTTP 500 Error". On Windows Vista and PHP 5.2.5.Got "extension=soap_php.dll" indicated in php.ini .
    I need some help. Thanks in advance.

    The client script is:

    <?php
    $client = new SoapClient("http://localhost/c7/server1.php&quot;);
    print($client->getQuote("ibm"));
    ?>

    And the server1.php script is:

    <?php
    $quotes = array("ibm" => 98.42);

    function getQuote($symbol) {
    global $quotes;
    return $quotes[$symbol];
    }

    $server = new SoapServer;
    $server->addFunction("getQuote");
    $server->handle();
    ?>

  16. mat_hew Says:

    abhikumar >
    why do you use two services and two bindings?
    you should use only one service and one binding to port type, which contain more operations

    and btw replace the urn: with some as http://myserver/soap/stockoperations

    :)

  17. abhikumar Says:

    I modified server1.php file as

    <?php

    class QuoteService {

    private $quotes = array("ibm" => 198.42);

    function getQuote($symbol) {

    if (isset($this->quotes[$symbol])) {

    return $this->quotes[$symbol];

    } else {

    throw new SoapFault("Server","Unknown Symbol ‘$symbol’.");

    }

    }

    function getPrice($str) {

    return "Take this price";

    }

    }

    ini_set("soap.wsdl_cache_enabled","0");

    //$data = file_get_contents(‘http://192.168.0.171/wsTest/client5.php’);

    $server = new SoapServer("http://192.168.0.171/wsTest/stockquote.wsdl&quot;);

    $server->setClass("QuoteService");

    $server->handle();

    ?>

    And modified wsdl file as

    <?xml version =’1.0′ encoding =’UTF-8′ ?>

    <definitions

    name=’StockQuote’

    targetNamespace=’urn:StockQuote’

    xmlns:tns=’urn: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>

    <message name=’getPriceRequest’>

    <part name=’symbol’ type=’xsd:string’/>

    </message>

    <message name=’getPriceResponse’>

    <part name=’result’ type=’xsd:string’/>

    </message>

    <portType name=’StockQuotePortType’>

    <operation name=’getQuote’>

    <input message=’tns:getQuoteRequest’/>

    <output message=’tns:getQuoteResponse’/>

    </operation>

    </portType>

    <portType name="StockPricePortType">

    <operation name="getPrice">

    <input message=’tns:getPriceRequest’ />

    <input message=’tns:getPriceResponse’ />

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

    <binding name=’StockPriceBinding’ type=’tns:StockPricePortType’>

    <soap:binding style=’rpc’

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

    <operation name=’getPrice’>

    <soap:operation soapAction=’urn:xmethods-delayed-quotes#getPrice’/>

    <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://192.168.0.171/wsTest/server1.php’/>

    </port>

    </service>

    <service name=’StockPriceService’>

    <port name=’StockPricePort’ binding=’StockPriceBinding’>

    <soap:address location=’http://192.168.0.171/wsTest/server1.php’/>

    </port>

    </service>

    </definitions>

    Client5.php reads like

    <?php

    $client = new SoapClient("http://192.168.0.171/wsTest/stockquote.wsdl&quot;,array(

    "trace" => 1,

    "exceptions" => 0));

    try

    {

    $client->getQuote("ibm");

    print "<pre>\n";

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

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

    print "Headers:\n".htmlspecialchars($client->__getLastRequestHeaders())."\n";

    print "</pre>";

    echo $client->getPrice("hi");

    }

    catch (SoapFault $exception)

    {

    echo ‘EXCEPTION=’.$exception;

    }

    ?>

    I am not able to $client->getPrice(‘hi’);

    Can you guys please guide me through the missing stuff or concept.
    1. One more thing i would like to pass multiple arguments to the functions …I will highly appreciate any pointers towards solutions or root of errors.

  18. greg19 Says:

    Is it possible to send and receive an xml ‘envelope’ object such as the following?

    <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"&gt;
    <env:Header>
    <n:alertcontrol xmlns:n="http://example.org/alertcontrol"&gt;
    <n:priority>1</n:priority>
    <n:expires>2001-06-22T14:00:00-05:00</n:expires>
    </n:alertcontrol>
    </env:Header>
    <env:Body>
    <m:alert xmlns:m="http://example.org/alert"&gt;
    <m:msg>Pick up Mary at school at 2pm</m:msg>
    </m:alert>
    </env:Body>
    </env:Envelope>

    If so, could you please provide an example using the php frame work?

    Thanks,
    Greg

  19. _____anonymous_____ Says:

    How can i made a soap request from php like :

    <searchrequest limit="10" offset="30">
    <query></query>
    </searchrequest>

    Thanks

  20. _____anonymous_____ Says:

    Get rid of the spaces before <?xml too…

    This may be getting you, too:

    http://bugs.php.net/bug.php?id=41293&edit=1

    M.

  21. _____anonymous_____ Says:

    good article.

    for the above users’ errors. try to catch the exception…
    i think this is where most peoples errors above are.

    <?php
    $client = new SoapClient("stockquote.wsdl",array(
    "trace" => 1,
    "exceptions" => 0));

    try
    {
    $client->getQuote("ibm");
    // or $client->__soapCall("getQuote", array("ibm"));
    }
    catch (SoapFault $exception)
    {
    echo ‘EXCEPTION=’.$exception;
    }

    ?>

  22. sailorarie Says:

    I am having the same problem, and i am not behind a proxy…

    PHP Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn’t load from ‘/home/www/login1/html/soap/stockquote.wsdl’ in /home/www/login1/html/soap/client3.php:2
    Stack trace:
    #0 /home/www/login1/html/soap/client3.php(2): SoapClient->__construct(‘stockquote.wsdl’)
    #1 {main}
    thrown in /home/www/login1.nl/html/soap/client3.php on line 2

    My 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://arie.mijnlieff.nl/soap/server1.php’/>
    </port>
    </service>
    </definitions>

    Replacing example.org doesnt work !

    I hope anyone can help us ?

  23. vizions Says:

    you have mistake in xml definition. Check the definition line and look for example.org and replace it with your server and path.

    -Vz-

  24. _____anonymous_____ Says:

    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).

    Soapvar? special object?

    Thanks

  25. ccochella Says:

    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>
    <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>

  26. jimdelong Says:

    In the above example, 1 value is returned. Are 2 values returned as an array? Or how would that be done?

  27. israelekpo Says:

    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.

  28. dangkhoi Says:

    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???
    Help me, help me to do.
    Thanks

  29. kroesjnov Says:

    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

  30. kroesjnov Says:

    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 ‘<?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)

  31. stromsky Says:

    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.