Green Acorn

Blog

Working with PHP NuSOAP

In this tutorial, I am going to show you how easy it is to work with SOAP using the NuSOAP PHP library.
Firstly, download the NuSOAP library here:

http://sourceforge.net/projects/nusoap/

Once you have downloaded the library, unzip the contents and copy the lib folder into your web root.

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-test

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__.

4 comments on “Working with PHP NuSOAP
  1. Pingback: Creating a Ruby SOAP Client | Green Acorn

  2. claudio peres on said:

    Would like your help, I’m a week without able to resolve this problem
    I have the url http://177.43.222.75/TESTE/VCSERVICOS_2/app.svc and method EmitirBoleto ($ xml) should return me this message in SOAPUI <! [CDATA [

    1

    Total fine not allowed R $ 226.6, expected R $ 124.63, to calculate 0.
    Total interest not allowed R $ 4,818.44, expected R $ 1,597.97, to calculate 0.
    Total fee not allowed £ 0, expected £ R $ 1,317.97, to calculate 0.
    Total 0 not allowed to increase, expected R $ 378.12, to calculate 0.

    ]]>

    but I get this message by nusoap
    stdClass Object
    (
    [EmitirBoletoResult] =>

    1

    String reference not set to an instance of a String.
    Parameter name: s

    $ xml =
    $xml5 = <<<XML5

    2014-09-22
    06403482629
    7
    PTO
    1.0

    12-13846/11

    2013-01-23 20
    2013-02-23 21
    2013-03-23 22
    2013-04-23 23
    2013-05-23 24
    2013-06-23 25
    2013-07-23 26
    2013-08-23 27
    2013-09-23 28
    2013-10-23 29
    2013-11-23 30
    2013-12-23 31
    2014-01-23 32
    2014-02-23 33
    2014-03-23 34
    2014-04-23 35
    2014-05-23 36
    2014-06-23 37
    2014-07-23 38
    2014-08-23 39

    2014-09-22

    11332.2
    4818.44
    226.6
    0
    0
    0
    0

    XML5;

    Would like your help, I’m a week without able to resolve this problem
    I have the url http://177.43.222.75/TESTE/VCSERVICOS_2/app.svc and method EmitirBoleto ($ xml) should return me this message in SOAPUI <! [CDATA [

    1

    Total fine not allowed R $ 226.6, expected R $ 124.63, to calculate 0.
    Total interest not allowed R $ 4,818.44, expected R $ 1,597.97, to calculate 0.
    Total fee not allowed £ 0, expected £ R $ 1,317.97, to calculate 0.
    Total 0 not allowed to increase, expected R $ 378.12, to calculate 0.

    ]]>

    but I get this message by nusoap
    stdClass Object
    (
    [EmitirBoletoResult] =>

    1

    String reference not set to an instance of a String.
    Parameter name: s

    $ xml =

    thank you so much

Leave a Reply

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

     

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>