Apache

Creating the SOAP server with NuSOAP

Creating the SOAP server

Create a file called food.php and copy the and paste the below code into it.

<?php
require_once "lib/nusoap.php";

class food {

    public function getFood($type) {
        switch ($type) {
            case 'starter':
                return 'Soup';
                break;
            case 'Main':
                return 'Curry';
                break;
            case 'Desert':
                return 'Ice Cream';
                break;
            default:
                break;
        }
    }
}

$server = new soap_server();
$server->configureWSDL("foodservice", "http://www.greenacorn-websolutions.com/foodservice");

$server->register("food.getFood",
    array("type" => "xsd:string"),
    array("return" => "xsd:string"),
    "http://www.greenacorn-websolutions.com/foodservice",
    "http://www.greenacorn-websolutions.com/foodservice#getFood",
    "rpc",
    "encoded",
    "Get food by type");

@$server->service($HTTP_RAW_POST_DATA);

Now lets break this down!

  • The first section of the above code is requiring the NuSOAP library.
  • The second part is a simple PHP class with one method called getFood
  • Next we initialise the soap_server class, configure the WDSL and register the class method.

Okay, so what are all those register parameters?

  • food.getFood is the className.methodName
  • array(“type” => “xsd:string”) defines the input argument to getFood and its data type i.e string, number, boolean
  • array(“return” => “xsd:string”) defines the method’s return value and its data type i.e string, number, boolean
  • http://www.greenacorn-websolutions.com/foodservice defines the namespace. Using a URI to identify a namespace, rather than a simple string (such as “food:webservice”), reduces the probability of different namespaces using duplicate identifiers.
  • http://www.greenacorn-websolutions.com/foodservice#getFood defines the SOAP action
  • rpc defines the type of call (this could be either rpc or document)
  • encoded defines the value for the attribute (encoded or literal could be used)
  • The last parameter is a documentation string that describes what the getFood method does

The WSDL

Now navigate to your web application via the browser. In my case I navigated to http://soap-test.dev/food.php?wsdl. Just be sure to include the ?wsdl. You should see an xml document like the one below. Save a copy of this in you web root and call it food.wsdl.

<?xml version="1.0" encoding="ISO-8859-1"?>
<definitions 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:tns="http://www.greenacorn-websolutions.com/foodservice" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://www.greenacorn-websolutions.com/foodservice">
    <types>
        <xsd:schema targetNamespace="http://www.greenacorn-websolutions.com/foodservice">
            <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
            <xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
        </xsd:schema>
    </types>
    <message name="food.getFoodRequest">
        <part name="type" type="xsd:string" />
    </message>
    <message name="food.getFoodResponse">
        <part name="return" type="xsd:string" />
    </message>
    <portType name="foodservicePortType">
        <operation name="food.getFood">
            <documentation>Get food by type</documentation>
            <input message="tns:food.getFoodRequest"/>
            <output message="tns:food.getFoodResponse"/>
        </operation>
    </portType>
    <binding name="foodserviceBinding" type="tns:foodservicePortType">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="food.getFood">
            <soap:operation soapAction="http://www.greenacorn-websolutions.com/foodservice#getFood" style="rpc"/>
            <input>
                <soap:body use="encoded" namespace="http://www.greenacorn-websolutions.com/foodservice" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
            </input>
            <output>
                <soap:body use="encoded" namespace="http://www.greenacorn-websolutions.com/foodservice" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
            </output>
        </operation>
    </binding>
    <service name="foodservice">
        <port name="foodservicePort" binding="tns:foodserviceBinding">
            <soap:address location="http://soap-test.dev/food.php"/>
        </port>
    </service>
</definitions>

Creating the SOAP client

Create a file called foodclient.php and copy the and paste the below code into it.

<?php
require_once "lib/nusoap.php";

$client = new nusoap_client("food.wsdl", true);
$error  = $client->getError();

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

$result = $client->call("food.getFood", array("type" => "Main"));

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>Main</h2>";
        echo $result;
    }
}

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

Now lets break this down too!

  • Initialise nusoap_client and tell it to accept a WSDL file. We could also do this: $client = new nusoap_client(“http://soap-test.dev/food.php”); However, using a WSDL file is considered best practice.
  • The getError method checks if their were any errors whilst creating the client.
  • The call method defines the RPC method and arguments and sends the SOAP request.
  • Errors are again checked and the results are outputted.
  • The last few lines of code are used to show the SOAP request and response (ideal for debugging)

Now let’s test

Navigate to your food client, in my case http://soap-test.dev/foodclient.php. You should now see results similar to the below:

soap-test2

Working with a proxy class

A proxy class is code that looks exactly like the class it meant to represent; however the proxy class doesn’t contain any of the application logic. Instead, the proxy class contains marshalling and transport logic.

To use a proxy class with the food soap client. Simple modify foodclient.php to look like the below:

<?php

require_once "lib/nusoap.php";

$client = new nusoap_client("food.wsdl", true);

$proxy = $client->getProxy();
echo $proxy->food__getFood('Main');

Due to the fact our methods are a part of the food class, we will need to prefix the proxy methods with food__.

Leave a Reply

Your email address will not be published. Required fields are marked *