26283 total geeks with 3498 solutions
Recent challengers:
 Welcome, you are an anonymous user! [register] [login] Get a yourname@osix.net email address 

Articles

GEEK

User's box
Username:
Password:

Forgot password?
New account

Shoutbox
MaxMouse
It's Friday... That's good enough for me!
CodeX
non stop lolz here but thats soon to end thanks to uni, surely the rest of the world is going good?
stabat
how things are going guys? Here... boring...
CodeX
I must be going wrong on the password lengths then, as long as it was done on ECB
MaxMouse
lol... the key is in hex (MD5: of the string "doit" without the "'s) and is in lower case. Maybe i should have submitted this as a challenge!

Donate
Donate and help us fund new challenges
Donate!
Due Date: May 31
May Goal: $40.00
Gross: $0.00
Net Balance: $0.00
Left to go: $40.00
Contributors


News Feeds
The Register
Irish deputy PM:
You want more tax
from Apple? Your
problem, not ours
Private equity firm
coughs for £1bn for
Websense
Violin welcomes new
grand master flash
flogger
Outsourcing
transfer "rumour"
O2 brushed off?
It"s happening ...
to THOUSANDS
David Cameron asks
UK biz to pay their
low, low taxes
Syrian hacktivists
hijack
Telegraph"
s Facebook, Twitter
accounts
Review: Sony Xperia
SP
BT Tower is just a
relic? Wrong: It
relays 18,000hrs of
telly daily
Curiosity
plunges its drill
into Mars AGAIN,
seeks life-giving
sample
Our new 1.5TB
lappie drive isn"t
thick, it"s just
the densest - HGST
Slashdot
Immigration Reform
May Spur Software
Robotics
Hollywood Studios
Use DMCA To Censor
Pirate Bay
Documentary
Inside the
Microsoft Digital
Crimes Unit
Working Handgun
Printed On a
Sub-$2,000 3D
Printer
Goodbye, Lotus
1-2-3
Australia Makes
Asian Language
Learning a Priority
Web of Tax Shelters
Saved Apple
Billions, Inquiry
Finds
German Researchers
Hit 40 Gbps On
Wireless Link
The Hunt For
LulzSec"s Missing
Sixth Member
Latvian Police Raid
Teacher"s Home for
Uploading $4.00
Textbook
Article viewer

PHP Web Services using SOAP



Written by:TroPe
Published by:NeorageX
Published on:2004-11-06 17:35:33
Topic:PHP
Search OSI about PHP.More articles by TroPe.
 viewed 36921 times send this article printer friendly

Digg this!
    Rate this article :
This tutorial will explain how to send and receive SOAP messages using NuSOAP (an open source set of classes) by building a web service from scratch. This tutorial should benefit both the beginner and intermediate PHP programmer interested in developing / consuming web services in PHP.

One example we'll look at is how you, as a Soprano mobster, can use a web service to quickly identify the life status of your enemy crime bosses so you don't expend useless hours planning their demise.

-----------------------------------------------
PHP Web Services using SOAP
-----------------------------------------------
Written by Giovanni Tropeano 11/2004
Prepared for OSIX


<<< Table of Contents >>>
  • ...Preface
  • ...Web Services Using NuSOAP
  • ...Installing, Configuring NuSOAP
  • ...Data Type Issues
  • ...Our First SOAP Client
  • ...Our First SOAP Server
  • ...Dealing with FAULTS
  • ...Using Arrays
  • ...WSDL and soap_proxy
  • ...Summary




Ok, today we'll take a look at using web services in PHP. All I can say about this one is...buckle up. This'll be a ride. I wrote this for one reason - I kept putting off learning this topic. First of all, PHP is not one of my strong points. Secondly, PHP is NOT one of my strong points :) But...this is OSIX. PHP and NuSOAP both Open Source. I couldn't resist. Thanks to my former employer for making me learn web services in PHP via hours and hours of online courses, heeeeere we go...


So what is NuSOAP you ask? Well, it's a collection of classes that allow you to send and receive SOAP messages over HTTP. It's distributed by the fine people at http://www.nusphere.com and yes, it's all open source.

NuSOAP isn't a PHP extension. It's written in pure PHP. This means all PHP developers, no matter what their web server permissions or restrictions are, can use it. Nice.

NuSOAP is a component-based Web Services toolkit. It employs a base class that provides utility methods such as variable and envelope serialization, as well as namespace information and mappings of different types to different namespaces. Web Service interaction is achieved through a high-level client class called soapclient. This high-level class allows users to specify options such as HTTP authorization credentialls, HTTP proxy information, as well as managing the actual sending and receiving of the SOAP message itself. It uses several helper classes to accomplish the sending and receiving of SOAP messages.

You can execute SOAP operations by passing the name of the operation to the call() method. If the service to be consumed provides a WSDL file (always nice when they do, huh?), the soapclient class takes the URL of the WSDL file as an argument to its constructor, and uses the wsdl class to parse the WSDL file and extract all the data. The WSDL class has methods that extract data on a per-operation or per-binding basis.

The soapclient uses this data from the WSDL file to encode parameters and create the SOAP envelope when the user executes a call to a service. When the call is executed, the soapclient class uses the soap_transport_http class to send the outgoing message and receive the incoming message. The incoming message is parsed using soap_parser class.

If the Web Service to be consumed doesn't provide a WSDL file (the bastards!), then the process is different. The URL of the service is passed to the soapclient class constructor. Operations are still executed using the call method of the soapclient object, but details that are otherwise provided by the WSDL file must be passed as arguments. Parameters that are custom types can be represented using the soapval classs, which allow users to customize a parameter's serialization. With me? Good, let's "install" NuSOAP.


Installing NuSOAP is easy. It's really just an include page. I'm sure you probably know this , but for the newbies... Follow these steps:

1. Download the files from url]http://dietrich.ganx4.com/nusoap/[/url].
2. Extract the file nusoap.php from its zip (if you chose the zip version).
3. For easy access, copy the classes to a location in your include path, or into the directory in which you'll be using the classes.
4. Include the class in your script. The path to nusoap.php can be relative or absolute:


   include('nusoap.php');



In my example, I have used the include() function to include the NuSOAP classes in my script. This function will generate a warning if the path to nusoap.php is incorrect, but will continue to process the rest of the script. There are other ways to do this though:


    require()



This function is identical to include(), but handles failure by spitting out a fatal error, which will halt processing of the script.

or...


    require_once()




Identical to require(), except that if the file to be included is already included in the script, it will not repeat the inclusion.

or...


    include_once()



Identical to include(), except that if the file to be included has been previously included in the script, it will not include it again.


SOAP and WSDL both make heavy use of the data types described in the XML Schema specification. This can be a problem since PHP does not natively support most of the data types defined in the specification. Also, the XML Schema data types are 'fine-grained' and 'explicitly defined', and PHP is a loosely-typed language and will convert data types automatically when deamed appropriate. NuSOAP solves this problem at three different levels (maybe more, but three that I know of):

1. In WSDL, NuSOAP's soapclient class will encode a value's type according to the type specified in the WSDL document.

2. The NuSOAP soapval class allows users to explicitly define a value's type.

3. If no type is explicitly declared when instantiating a soapval object, NuSOAP will analyze the value passed to it using PHP's built-in variable introspection functions as well as regular expressions and other means where necessary, and classify it as a valid XML Schema data type.



We're going to start off really simple. Our Web Service will accept a string as a parameter, and echo it to the screen. Probably won't impress the hottie down the block, but...we have to start somewhere.

I'm going to demonstrate the basic process of creating a SOAP client, calling a SOAP service and passing it parameters, and receiving the response. We will name this file echoStringClient.php.

We'll use the require() function in our examples because we'd like the script to halt execution if it cannot find the NuSOAP file:


   <?php
   require('nusoap.php');



Let's create a variable for the string we'd like to send.


   $myString = 'I learned this from OSIX';



Our parameters must be passed as an array to the SOAP client, so let's create one:


   $parameters = array($myString);



Now we can instantiate the soapclient object. It takes the URL of the server as an argument to its constructor:


   $s = new soapclient('http://MySite.com/echoStringServer.php');



This step is where all the magic takes place. Using the call() method, we tell the soapclient object which service we'd like to access, then pass our array of parameters, and the method then returns the response from the server. This response is a PHP native type, such as a string, integer, or array. It is the result of the decoding that takes place when NuSOAP parses the response message:


   $result = $s->call('echoString',$parameters);



NuSOAP offers error detection through the getError() method. If an error has occurred this method returns a string describing the error, and returns false otherwise. In our example, we print our result after checking for errors if there are none. If there are errors, we'll print the error message:


   if(!$err = $s->getError()){
       echo 'Result: '.$result;
   } else {
       echo 'Error: '.$err;
   }



You might find this last bit of code helpful for debugging SOAP operations. The request and response properties of the soapclient class contain strings of the respective messages, including the HTTP headers sent with each:


   echo '<xmp>'.$s->request.'</xmp>';
   echo '<xmp>'.$s->response.'</xmp>';
   ?>



SOAP Request and SOAP Response

Here is the request message from our example:


   POST /echoStringServer.php HTTP/1.0
   User-Agent: NuSOAP v0.6.1
   Host: localhost
   Content-Type: text/xml
   Content-Length: 569
   SOAPAction: ""

   <?xml version="1.0" encoding="ISO-8859-1"?>
   <SOAP-ENV:Envelope
     SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
     xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
     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/"
     xmlns:si="http://soapinterop.org/xsd">
   <SOAP-ENV:Body>
     <nu:echoString xmlns:nu="http://testuri.org">
       <soapVal xsi:type="xsd:string">I learned this from OSIX</soapVal>
     </nu:echoString>
   </SOAP-ENV:Body>
   </SOAP-ENV:Envelope>



Below is the server's response message from our kick ass high tech example. Notice that the first element in the body of the message is the name of the operation we called, with Response appended to it. Also, the element name of the return value is called return. Both of these are standard practice for serializing SOAP responses:


HTTP/1.1 200 OK
   Server: Microsoft-IIS/5.0
   Date: Fri, 04 Nov 2004 18:47:53 GMT
   X-Powered-By: PHP/4.1.2
   Status: 200 OK
   Server: NuSOAP Server v0.6.1
   Connection: Close
   Content-Type: text/xml; charset=UTF-8
   Content-Length: 1525

   <?xml version="1.0" encoding="ISO-8859-1"?>
   <SOAP-ENV:Envelope
     SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
     xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
     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/"
     xmlns:si="http://soapinterop.org/xsd">
   <SOAP-ENV:Body>
     <echoStringResponse>
       <soapVal xsi:type="xsd:string">I learned this from OSIX</soapVal>
     </echoStringResponse>
   </SOAP-ENV:Body>
   </SOAP-ENV:Envelope>




This example is the server that was accessed by our client example. It implements the echoString service.

The first step as usual is to include the NuSOAP classes:


   <?php

   require('nusoap.php');



Now we can instantiate the server object, provided by the soap_server class:


   $s = new soap_server;



To allow our function to be called remotely, we must register it with the server object. If this is not done, the server will generate a fault indicating that the service is not available if a client accesses the service. In the absence of such a registration process, any PHP functions would be remotely available, which would present a serious security risk:


   $s->register('echoString');



Now we can define our function that we are exposing as a service. Notice that we first check to make sure a string was passed. If the parameter is not a string, we use the soap_fault class to return an error to the client indicating that they must pass a string value as the parameter to this function:


   function echoString($inputString){

       if(is_string($inputString)){
           return $inputString;
       } else {
           return new soap_fault('Client','','Hey! Pass me a string would ya!.');
       }
   }



The final step is to pass any incoming posted data to the SOAP server's service method. This method processes the incoming request, and calls the appropriate function. It will then formulate the ressponse, and print it:


   $s->service($HTTP_RAW_POST_DATA);

   ?>




The properties of the soap_fault class are below. These are also the arguments to the soap_fault constructor, in the same order as below:

Fault Name: faultcode

This property MUST have a value. The values available to the user are Client and Server. Client class errors indicate that the message didn't contain the information required for the operation to succeed. Server class errors indicate processing problems on the server.

Fault Name: faultactor

This property is not functional yet in NuSOAP, and can be left empty. Not sure why they even put it in their documentation. And not sure why I put it in here!

Fault Name: faultstring

This is a human-readable error message. This is the best place for you to describe errors.

Fault Name: faultdetail

The value of the faultdetail property is XML data used to detail the specific errors related strictly to the Body element of the SOAP message. You can insert your own XML markup here if you'd like to.

The soap_fault class has only one method besides the constructor that is serialize(). The serialize() method takes the fault information and serializes it, returning a complete SOAP message.

An example of using the soap_fault class is shown here:


   $fault = new soap_fault(
        'Client','','Whassamatta wit you huh, the inputString parameter cannot be empty!');

   echo $fault->serialize();



The SOAP message below is what is returned by the serialize() method of the soap_fault object instantiated above:


   <?xml version="1.0"?>
   <SOAP-ENV:Envelope
   SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
     xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
     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/"
     xmlns:si="http://soapinterop.org/xsd">
   <SOAP-ENV:Body>
   <SOAP-ENV:Fault>
     <faultcode>Client</faultcode>
     <faultactor></faultactor>
     <faultstring>Whassamatta wit you huh, the inputString parameter cannot be empty!</faultstring>
     <detail></detail>
   </SOAP-ENV:Fault>
   </SOAP-ENV:Body>
   </SOAP-ENV:Envelope>





Transmitting and receiving arrays is transparently done in NuSOAP. You can pass PHP arrays in the parameters array argument to the soapclient class's call method, and NuSOAP will detect the type of the array contents, and serialize accordingly. This next example uses a service called echoArray that accepts an array and returns the same array.

Homework: While running this example, try modifying the parameter array by adding different data types, and see how the serialization changes. Sweet huh?

First, include the NuSOAP classes:

   <?php

   require('nusoap.php');



Create the array we'd like to send:


   $arr = array('string1','string2');



Create the array of parameters:


   $parameters = array($arr);



Instantiate the soapclient object, passing it the endpoint URL:


   $s = new soapclient('http://MySite.com/echoStringServer.php/echoArrayServer.php');



Now we call the echoArray operation, passing it our array of parameters, and receive the result. Then print the result on the screen, and view the request and response messages, as follows:


   $result = $s->call('echoArray',$parameters);

   if(!$err = $s->getError()){
        echo 'Result: '.$result;
   } else {
        echo 'Error: '.$err;
   }

   echo '<xmp>'.$s->request.'</xmp>';
   echo '<xmp>'.$s->response.'</xmp>';

   ?>




WSDL is an XML language used to describe a Web Service. It is a machine-readable format that provides Web Service clients with all the information necessary to access the service. NuSOAP provides a class for parsing WSDL files, and extracting data from them. The soapclient object uses the wsdl class to ease the burden of the developer callling a service. With the help of the WSDL data to create messages, you only need to know the name of the operation to call, and the parameters required by the operation.

Using WSDL with NuSOAP provides several benefits in my opinion:

Benefit #1: All service meta data such as namespaces, endpoint URLs, parameter names, and much more are read from the WSDL, allowing the client to dynamically cope with changes from the server. This information no longer needs to be hard-coded into the user's script since it's on the server.

Benefit #2:It allows us to use the soap_proxy class. This class is an extended soapclient class with new methods for each of the operations detailed in the WSDL file. Now you can call these methods directly. I will describe this process below.

The soapclient class contains a method called getProxy(). This method returns an object of the class soap_proxy. The soap_proxy class extends the soapclient class with methods that correspond to the operations defined in the WSDL document, and allows users to call the remote methods of an endpoint as if they were local to the object. This is only functional when the soapclient object has been instantiated using a WSDL file and has the advantage of easy access for a user.

Mobster WSDL example



Okay, it's important for mobsters to know the life status of their enemies. Imagine if you planned to whack someone and they were already dead? You have just wasted many hours of drinking at the titty bar and planning this hit. So, you'd better call on your handy dandy Mobster web service to quickly help you.

Here is an example of using WSDL to call your service, using the soap_proxy class. We start by including the NuSOAP classes:


   <?php

   include('nusoap.php');



When instantiating the client object using WSDL, we pass the URL or path to the WSDL file as an argument to the constructor, as well as an argument that lets the client know we've passed it WSDL and not a SOAP endpoint:


   $s = new soapclient('http://MyMobSite.com/soap/urn:whack_status.wsdl', 'wsdl');



Now we'll generate the proxy class. This is achieved by invoking the getProxy() method of the soapclient class:


   $p = $s->getProxy();



We can now invoke the remote method as a method of the proxy class, and pass our parameters directly. The proxy object will handle the details such as matching up parameter values to their names, assigning namespaces, and types:


   $lifeStatus = $p->getMobsterStatus('Bugsy');



Lastly let's check for errors, and if none are present print out the results:


   if(!$err = $p->getError()){
        print "That mobster life status is: $lifeStatus .";
   } else {
        print "ERROR: $err";
   }

   print '<xmp>'.$p->request.'</xmp>';
   print '<xmp>'.str_replace('><',">\n<",$p->response).'</xmp>';

   ?>



Our code may produce the following:

That mobster life status is: DEAD. No need to Whack!

(quick note to all potential mobsters: this is a ficticious web service. please do not use this to plan your whacks.)


Well, thanks for reading this. I had a blast writing it, and brushing up on my PHP. As I mentioned, I am NOT an expert at PHP. There may be other ways to achieve easy web services in PHP, but this way just seemed to be easiest for me.

And the migration for me continues...slowly converting to PHP from .NET and loving the ride.

TroPe

Did you like this article? There are hundreds more.

Comments:
bb
2004-11-08 14:12:06
i might have a go at doing some soap from our box for the site. i, like you, am a .net developer, and enjoy how easy it is to include soap references in my applications. i did once try installing some php soap toolkit inside PEAR, but things went horribly wrong, and i havent been back since.
TroPe
2004-11-09 22:02:27
how about a web service that will return my (a users) points? that would be great practice and fairly easy to invoke.
bb
2004-11-11 13:50:15
yeah could do.

we already include a simple php page for that purpose, which is parsed by a bot, so scores etc can be checked from the irc channel. but soap would be a cool test for such a thing
aidan
2005-06-03 11:26:45
cool tutorial. Just what i was looking for!
here's a link to NuSOAP at sourceforge
Anonymous
2008-03-04 13:21:52
hein?
Anonymous
2008-09-08 21:22:05
Thanks, finally someone who can put things easy...
Anonymous
2009-02-17 10:29:43
checking...
it seems it wil not wrk... bt whats this... it is wrkin........
Anonymous
2009-06-26 04:09:15
can i see the code for the server side of this example web service.
Anonymous
2009-09-25 07:33:31
test
Anonymously add a comment: (or register here)
(registration is really fast and we send you no spam)
BB Code is enabled.
Captcha Number:


Blogs: (People who have posted blogs on this subject..)
elasolova
My PHP Projects on Sat 26th Sep 10am
I have been developing PHP applications for almost a year now. I have developed three projects. One is a simple trivia game. The other is a question-answer based community at http://www.javaist.com/quans . The last one is a programming challenge site just
countll
Blog entry for Thu 25th Oct 7am on Thu 25th Oct 7am
soo nu on this wicked world of NET. just decided to dive in today..hope friend aroun here can help

Test Yourself: (why not try testing your skill on this subject? Clicking the link will start the test.)
Test of experience (hopefully) by AcidIce

Things you're only likely to know if you've actually written a lot of PHP before :)


     
Your Ad Here
 
Copyright Open Source Institute, 2006