Introduction into SOAP, setting up a simple webservice with PHP SOAP

I was asked to create a simple webservice that would allow us to transfer a intranet post to an external CMS. In this post I will explain the steps you must take to set-up a simple webservice with the PHP SOAP extension.

The first step, create a simple class that we will use to request data from
We will create a class with one method that returns a string with the parameter we called it. The method will accept one parameter and will check if the value is correct.


<?php
/**
 * Blog service class
 */
class BlogService
 {
    /**
     * Return a blogpost
     *
     * @param string $sID
     * @return string test data
     */
     public function getItem($sID)
     {
         $iID       = (int)$sID;
         $aValidIds = array(1, 2, 3, 5); // Notice the missing id number 4

         // Check if we requested a valid blogpost id
         if(!in_array($iID, $aValidIds)) {
             return new SoapFault('Server', 'Blogpost with id '.$iID.' not found!');
         }
         
         return 'Blogpost with id '.$iID;
     }
 }
?>

Nothing special here, notice that we don’t throw a normal exception but return the SoapFault instead so we can handle the error clientside.

The second step, create a WSDL document

The WSDL document is a simple XML document that describes:

The WSDL will describe our method getItem from our Blog service class so we can call it later on.

So how does this WSDL thing look like?

<?xml version="1.0" encoding="UTF-8" ?>
<definitions name="Entities"
            targetNamespace="urn:blog"
            xmlns:typens="urn:blog"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
            xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns="http://schemas.xmlsoap.org/wsdl/">
    <types>
        <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:blog">
        </xsd:schema>
    </types>

    <message name="getItemResponse">
        <part name="string" type="xsd:string" />
    </message>

     <message name="getItemRequest">
        <part name="return" type="xsd:string" />
    </message>

    <portType name="blogPortType">
        <operation name="getItem">
            <documentation>Returns a simple test string</documentation>
            <input message="typens:getItemRequest" />
            <output message="typens:getItemResponse" />
        </operation>
    </portType>

    <binding name="blogBinding" type="typens:blogPortType">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>

        <operation name="getItem">
            <soap:operation soapAction="urn:blog#getItem" style="rpc" />
            <input>
                <soap:body use="encoded" namespace="urn:blog" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </input>
            <output>
                <soap:body use="encoded" namespace="urn:blog" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </output>
        </operation>
        
    </binding>

    <service name="blog">
        <port name="blogPort" binding="typens:blogBinding">
            <soap:address location="http://{siteUrl}/webservice/server.php" />
        </port>
    </service>
</definitions>

As you can see the WSDL consists of different parts:

The third step, map our Blog service class to the webserver

After we have created our WSDL we can start building our server. In just a few lines we have a SOAP server up and running.


 // Init the server
$oServer = new SoapServer('blog.wsdl');

// Register the blog service class and all the methods
$oServer->setClass('BlogService');

// Rock 'n roll
$oServer->handle();

The fourth and final step, test our webservice

Its a good idea to test the webservice with a program like soapUI, it often can provide some additional information when troubleshooting. (They have a free version available on their website).

To test our webservice in PHP we can use the following code:


ini_set("soap.wsdl_cache_enabled", "0"); // Disable the wsdl cache

$oClient = new SoapClient(
                // Url to our wsdl, http://{siteUrl}/webservice/index.php?wsdl is also possible
                '{siteUrl}/webservice/blog.wsdl', 
                array(
                    'trace'  => true,
                    'exceptions'=> true
                ));

try {
    $aResult = $oClient->getItem(4);
    var_dump($aResult);
} catch (SoapFault $e) {
    exit($e->faultstring);
}

You should see a SOAP fault, because the id number 4 we gave to the getItem function didn’t exist in our Blog service class. Change the value to 1,2,3 or 5 and you should get a nice response back.
Another pretty neat function is $oClient->__getFunctions(); it will return all the function that are available in the webservice.

This was just a short introduction to SOAP, a lot more is possible with SOAP.
Special thanks to David Zuelke for the nice SOAP introduction at the PHPbenelux conference 2010.

Example files:
Webservice.rar (no longer online)

Just deploy the example files on your webserver, change the {siteUrl} values in the files with your domain and call the client.php