Creating Web Services with PHP and SOAP, Part 1

This entry is part 1 of 2 in the series Creating Web Services with PHP and SOAP

Creating Web Services with PHP and SOAP

As application developers, the ability to develop software and services for a wide range of platforms is a necessary skill, but not everyone uses the same language or platform and writing code to support them all is not feasible. If only there was a standard that allowed us to write code once and allow others to interact with it from their own software with ease. Well luckily there is… and it’s name is SOAP. (SOAP used to be an acronym which stood for Simple Object Access Protocol, but as of version 1.2 the protocol goes simply by the name SOAP.)

SOAP allows you to build interoperable software and allows others to take advantage of your software over a network. It defines rules for sending and receiving Remote Procedure Calls (RPC) such as the structure of the request and responses. Therefore, SOAP is not tied to any specific operating system or programming language. As that matters is someone can formulate and parse a SOAP message in their chosen language

In this first of a two part series on web services I’ll talk about the SOAP specification and what is involved in creating SOAP messages. I’ll also demonstrate how to create a SOAP server and client using the excellent NuSOAP library to illustrate the flow of SOAP. In the second part I’ll talk about the importance of WSDL files, how you can easily generate them with NuSOAP as well, and how a client may use a WSDL file to better understand your web service.

The Structure of a SOAP Message

SOAP is based on XML so it is considered human read, but there is a specific schema that must be adhered to. Let’s first break down a SOAP message, stripping out all of its data, and just look at the specific elements that make up a SOAP message.

<?xml version="1.0"?>
<soap:Envelope
 xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
 soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
 <soap:Header>
  ...
 </soap:Header>
 <soap:Body>
  ...
  <soap:Fault>
   ...
  </soap:Fault>
 </soap:Body>
</soap:Envelope>

This might look like just an ordinary XML file, but what makes it a SOAP message is the root element Envelope with the namespace soap as http://www.w3.org/2001/12/soap-envelope. The soap:encodingStyle attribute determines the data types used in the file, but SOAP itself does not have a default encoding.

soap:Envelope is mandatory, but the next element, soap:Header, is optional and usually contains information relevant to authentication and session handling. The SOAP protocol doesn’t offer any built-in authentication, but allows developers to include it in this header tag.

Next there’s the required soap:Body element which contains the actual RPC message, including method names and, in the case of a response, the return values of the method. The soap:Fault element is optional; if present, it holds any error messages or status information for the SOAP message and must be a child element of soap:Body.

Now that you understand the basics of what makes up a SOAP message, let’s look at what SOAP request and response messages might look like. Let’s start with a request.

<?xml version="1.0"?>
<soap:Envelope
 xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
 soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
 <soap:Body xmlns:m="http://www.yourwebroot.com/stock">
  <m:GetStockPrice>
   <m:StockName>IBM</m:StockName>
  </m:GetStockPrice>
 </soap:Body>
</soap:Envelope>

Above is an example SOAP request message to obtain the stock price of a particular company. Inside soap:Body you’ll notice the GetStockPrice element which is specific to the application. It’s not a SOAP element, and it takes its name from the function on the server that will be called for this request. StockName is also specific to the application and is an argument for the function.

The response message is similar to the request:

<?xml version="1.0"?>
<soap:Envelope
 xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
 soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
 <soap:Body xmlns:m="http://www.yourwebroot.com/stock">
  <m:GetStockPriceResponse>
   <m:Price>183.08</m:Price>
  </m:GetStockPriceResponse>
 </soap:Body>
</soap:Envelope>

Inside the soap:Body element there is a GetStockPriceResponse element with a Price child that contains the return data. As you would guess, both GetStockPriceResponse and Price are specific to this application.

Now that you’ve seen an example request and response and understand the structure of a SOAP message, let’s install NuSOAP and build a SOAP client and server to demonstrate generating such messages.

Building a SOAP Server

It couldn’t be easier to get NuSOAP up and running on your server; just visit sourceforge.net/projects/nusoap, download and unzip the package in your web root direoctry, and you’re done. To use the library just include the nusoap.php file in your code.

For the server, let’s say we’ve been given the task of building a service to provide a listing of products given a product category. The server should read in the category from a request, look up any products that match the category, and return the list to the user in a CSV format.

Create a file in your web root named productlist.php with the following code:

<?php
require_once "nusoap.php";

function getProd($category) {
    if ($category == "books") {
        return join(",", array(
            "The WordPress Anthology",
            "PHP Master: Write Cutting Edge Code",
            "Build Your Own Website the Right Way"));
	}
	else {
            return "No products listed under that category";
	}
}

$server = new soap_server();
$server->register("getProd");
$server->service($HTTP_RAW_POST_DATA);

First, the nusoap.php file is included to take advantage of the NuSOAP library. Then, the getProd() function is defined. Afterward, a new instance of the soap_server class is instantiated, the getProd() function is registered with its register() method.

This is really all that’s needed to create your own SOAP server – simple, isn’t it? In a real-world scenario you would probably look up the list of books from a database, but since I want to focus on SOAP, I’ve mocked getProd() to return a hard-coded list of titles.

If you want to include more functionality in the sever you only need to define the additional functions (or even methods in classes) and register each one as you did above.

Now that we have a working server, let’s build a client to take advantage of it.

Building a SOAP Client

Create a file named productlistclient.php and use the code below:

<?php
require_once "nusoap.php";
$client = new nusoap_client("http://localhost/nusoap/productlist.php");

$error = $client->getError();
if ($error) {
    echo "<h2>Constructor error</h2><pre>" . $error . "</pre>";
}

$result = $client->call("getProd", array("category" => "books"));

if ($client->fault) {
    echo "<h2>Fault</h2><pre>";
    print_r($result);
    echo "</pre>";
}
else {
    $error = $client->getError();
    if ($error) {
        echo "<h2>Error</h2><pre>" . $error . "</pre>";
    }
    else {
        echo "<h2>Books</h2><pre>";
        echo $result;
        echo "</pre>";
    }
}

Once again we include nusoap.php with require_once and then create a new instance of nusoap_client. The constructor takes the location of the newly created SOAP server to connect to. The getError() method checks to see if the client was created correctly and the code displays an error message if it wasn’t.

The call() method generates and sends the SOAP request to call the method or function defined by the first argument. The second argument to call() is an associate array of arguments for the RPC. The fault property and getError() method are used to check for and display any errors. If no there are no errors, then the result of the function is outputted.

Now with both files in your web root directory, launch the client script (in my case http://localhost/nusoap/productlistclient.php) in your browser. You should see the following:

If you want to inspect the SOAP request and response messages for debug purposes, or if you just to pick them apart for fun, add these lines to the bottom of productlistclient.php:

echo "<h2>Request</h2>";
echo "<pre>" . htmlspecialchars($client->request, ENT_QUOTES) . "</pre>";
echo "<h2>Response</h2>";
echo "<pre>" . htmlspecialchars($client->response, ENT_QUOTES) . "</pre>";

The HTTP headers and XML content will now be appended to the output.

Summary

In this first part of the series you learned that SOAP provides the ability to build interoperable software supporting a wide range of platforms and programming languages. You also learned about the different parts of a SOAP message and built your own SOAP server and client to demonstrate how SOAP works.

In the next part I’ll take you deeper into the SOAP rabbit hole and explain what a WSDL file is and how it can help you with the documentation and structure of your web service.

Comments on this article are closed. Have a question about PHP? Why not ask it on our forums?

Image via Lilyana Vynogradova / Shutterstock

Creating Web Services with PHP and SOAP

Creating Web Services with PHP and SOAP, Part 2 >>

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Doug Johnson

    I’d be interested (after part 2 on SOAP) in your take on REST vs. SOAP.

  • Dan Soap

    Hi Stephen,
    good introduction into the world of SOAP servers and clients.

    I’m just wondering, is there a specific reason you work with NuSOAP (which has not been developed any further since 2010) instead of the SoapServer/SoapClient classes that come with PHP5?

    It would give you proper exception handling, supports SOAP 1.2, can handle SOAP headers well and by now with nearly every web hoster supporting PHP5…

    Best Regards,

    Dan

    • Stephen Thorpe

      @Dan Thanks for the comment. I chose to go with NuSOAP because of the built in WSDL generation and wanted to keep things simple not jumping to different frameworks and tools. This article is supposed to be for beginners to understand SOAP and web services and it’s just another way to do something.

      • sarmenhb

        have you tried php’s SoapClient function? if yes, do you think Nusoap is better? if yes can you please explain how and why? thanks

        • Stephen Thorpe

          @sarmenhb Yes I have tried the native PHP5 Soap classes and like them a lot. I had to build an application that required WS Security and chose that path even though I still had to extend the native class because PHP5 didn’t support WS. For the record I like the native PHP SOAP functions a bit better then NuSOAP, but for the tutorial I thought with the topics I was covering, it was easier to understand, keeping it together with one quick download of NuSOAP. Also not everyone has the luxury of always having a PHP5 server to maintain or work with. I have had to find multiple ways of doing things for legacy systems with older versions of PHP running on them. I always say it’s good to have multiple tools in your tool belt. Thanks for the comment.

  • http://www.sharafatalee.com Ali

    Quite useful article for someone like me to start on SOAP.

  • http://www.phpgurru.com Shafiq Rehman

    @stephen great article for SOAP beginners but I would like to suggest that you must use php5’s built-in soap library instead nusoap

  • boen_robot

    Nusoap? Seriously? Please tell me you aren’t planning to use that in the upcoming parts.

    PHP has a SOAP extension, and for WSDL generation, there’s Zend framework’s Zend_Soap_AutoDiscover.

    • Guilherme Franco

      I agree with boen. You should encourage developers to use the PHP built in extensions. That’s one of the reasons that make PHP have sort of a bad reputation for other language’s programmers. “Oh, PHP don’t have a built in SOAP extension, you have to download one. Oh, that sucks…” C’mon man, help us out here. Let’s professionalize PHP more and more !

  • Theodore R. Smith

    It is my professional opinion that advocating NuSOAP with complete disregard and non-mention of PHP’s internal C-based SOAP extension is pretty bad.

    NuSOAP is a great way to bring performance WAYYY down, and last time I checked, SOAP by itself adds a LOT more latency than even REST and substantially more than querying a DB.

    NuSOAP still doesn’t support SOAP v1.2, SSL, or any MS IIS SOAP servers that don’t go out of their way to be NuSOAP compatible. I remember it being a complete pain in the ass to work with.

    Additionally, NuSOAP’s API isn’t nearly as clean and concise as PHP’s.

  • sarmenhb

    rather than nusoap php has a function named SoapClient which can be used.
    http://php.net/manual/en/book.soap.php
    but thanks steph, you beat me to this article i was going to write one for soap but didnt have the time.

  • http://kahancreations.com Amit Sidhpura

    Hi Stephen,
    Nice article…Keep it Up!
    Thanks,

  • http://www.scriptvenue.com Arvind

    Hi Nice article !!!!

    But “nusoap.php” does not working. Please avail me a link to “nusoap.php” file.

    One more thing, i think my problem would be solved. Can you write an article for sms gateway Please…

  • http://www.4xlots.com PHK Corporation

    A useful tool when developing SOAP services is SoapUI. There is both a windows and Mac version.
    Also we use NuSoap for our web services for determining the optimal trading lot size and is free to use. You can try it out at 4xlots.com. Using the SoapUI tool to send and receive requests.

  • sarmenhb

    instead of using $HTTP_RAW_POST_DATA use
    $post = file_get_contents(‘php://input’);
    because it requires you to enable something in php.ini and i had problems with it myself.

    • jeronimo

      file_get_content is disabled on many servers

  • http://www.ioslearner.com Rons Micheal

    I was exactly looking on how to implement web services in PHP. My hosting account supports only PHP, and i know Java for server side. Your code worked great. Thanks :)

  • Daniel

    Thanks a lot, this is really useful

  • http://www.justiworld.com N Singh

    its very helpful article for me. I am beginner in SOAP and its awesome…

  • Wakidi

    Hi, nice tutorial…
    i have tried your tutorial in http mode and it runs well, but when i’m using https protocol it doesn’t work well…is there any configuration or modification in nusoap.php?
    Thanks a lot…

  • fatemeh

    thank you for your tutorial.but i have problem with invoking webservice.i get this error:
    Response not of type text/xml: text/html; charset=ISO-8859-1
    any suggest?

    • rrv

      I get the same error than fatemeh:
      Response not of type text/xml: text/html;
      help please!

  • Ash

    Hello,
    Nice tutorial. I have executed part 1 of it and it works fine on wamp server.

  • Adarsh

    It gives me error like “Fatal error: Maximum execution time of 30 seconds exceeded” What can I do???plz help me and other question can I use this service in ANDROID? and how?

  • http://www.wsdltophp.com Mikaël DELSOL

    Hi,
    To full abstract the SoapClient wihtout dealing with it directly, I would advise to use a Wsdl to PHP generator so you only deal with objects and call methods which map to the Web service operations.
    To try this, go to http://www.wsdltophp.com, I would be pleased to have your feedback,
    best regards,