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:

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__.
![]()
