This is a short series on how to create a PHP SOAP based web service and WSDLs. We will start with setting up the developer environment, move on to a simple “Hello World” example and then move through a few examples of increasing complexity. Hopefully after this is done we can expand on the examples to create a web service as simple or as complex as we want. We will also build a simple client interface for each service to demonstrate how to access the new web service.

Requirements for this project:

  • Access to install php extensions on your web server (if SOAP is not enabled)
  • Access to restart your web server (if SOAP is not enabled)
  • Access to Eclipse IDE (or ability to download and install Eclipse IDE)
  • Apache Web Server preinstalled
  • PHP 5.2+ preinstalled

A WSDL will provide your clients a quick way to integrate with your web service. It describes – in a way that SOAP understands – how to talk to the web service. It lists parameters the different functions expect and return. Some of the more advanced languages (and IDEs) can generate classes directly from the WSDL, making client side coding a breeze. PHP client coding isn’t quiet as easy, but we’ll work through that when we get there. First, we need to create a web service that we can talk to.

Development Environment Setup

Step one in this process is setting up the developer environment. In my case, I use the Eclipse IDE with the PDT plug in. As of this writing I was using the PDT 2.1 All in One / Eclipse PHP Package. Download the version appropriate your your operating system. Install Eclipse once it has been downloaded. The PDT plugin will already be installed if you used the above All in One package.

The next step is to configure the environment for this project. The first thing I do is set up the templates for PHP code to match my coding style. I like my curly braces at the beginning of a new line. This makes it easier to quickly identify unmatched braces and easily separates blocks of code from one another visually. It is a step that can easily be skipped, but it makes me happier as a programmer. Thus, I do it. To change code block templates go to Window->Preferences->PHP->Code Style->Code Templates and select Code. Now go through each and change to the appropriate format you would like. One thing you may wish to consider changing is “Simple php file” and include the closing

?>

By doing just that one change, whenever a new PHP file is created you will automatically have the opening and closing tags, with the cursor between them.

Hello World Web Service (Our First Web Service)

The next step, is starting a web service project.

Go to File->New->Project. This will open a new Dialog window. From here select Web->Static Web Project

New Web Project selection

New Web Project selection

Insert a name for your project. It will show you where all your files related to this project will be saved. Select Finish.

Insert new project name

Insert new project name

Your new project should now show up in the project list. We are ready to begin.

Your new project now appears in the project list.

Your new project now appears in the project list.

Creating the Web Service Definition Language (WSDL)

Right click on your new project. Select New->Other. This will open a dialog box. In here select Web Services->WSDL.

WSDL File Type selection

WSDL File Type selection

On the next screen, select your project and give your WSDL a name. For this example we will call it ZeroWebservice.wsdl. Enter a name space. In this case it was “ZeroWebservice”. Finally, select “rpc literal” for SOAP Binding Options.

Select 'rpc literal' and enter a namespace

Select 'rpc literal' and enter a namespace

We now have our WSDL skeleton. Something to work with!

Initial WSDL

Initial WSDL

What does the above mean? The right hand box is the description to the world on how to access your Web Service. In the Initial WSDL you have a single input and a single output. Both of these are in the function NewOperation, which is what the world would call to access your service.

Now we need to modify it to do something. We are  going to pass in a string (likely a user name) and get a string back. Let’s change the names of our parameters to “input” and “result”. Do this by selecting the ‘parameters’ and changing the name as appropriate.

Input and Output parameters changed to meaningful names

Input and Output parameters changed to meaningful names

Next, let’s make our values mean something. First we are going to change the function name from “NewOperation” to “sayHelloWorld”. Do this by double clicking on “NewOperation” (in the blue box on the right). After you have changed it, you will notice that the parameter responses also changes to “sayHelloWorldResponse” and “sayHelloWorldRequest”. This is a good thing.

The next step is to change the output from “parameters” to a simple string response. Parameters will be useful in our later examples, but for right now, we just want the Web Service to say “Hello World”. Click on the word “parameters” and then go to the properties tab along the bottom of the screen. If you don’t see a properties tab, go to Window->Show View->Other, then expand the General Tree and select “Properties”.

In the properties tab, change “Reference Kind” to “Type” and from the drop down above, select “string”.

This is our final sayHelloWorld Function

This is our final sayHelloWorld Function

Remember that a WSDL is just a description of behind the scenes code. It is not actual code to make something occur. It is your contract with the world on how to access your system remotely. With a well written WSDL, you change change the backend from PHP to .NET to Java to any other language that supports web services. As long as you abide by the WSDL, your end users will never have to change anything.

On the left hand box, you should see an inner text box with a link to example.org. Select that, and change it to where your will host the Web Service server code. This can be anywhere. If you want to see the full link, you will need to look in the properties tab below.

Destination for ZeroWebservice has now changed

Destination for ZeroWebservice has now changed

Next, lets set up ports and bindings with proper names. Above the target you just changed, double click on ZeroWebserviceSOAP and change this to ‘ZeroWebservicePort’. In the Properties tab change the binding name to ‘ZeroWebserviceBinding’. You may need to click ‘New…’ to do this. If you do, select and delete the new box that appears in the display. The next step is to select the ‘Binding’ box (the little square between the two big ones) and change the name to ‘ZeroWebserviceBinding’ and the Port Type to ZeroWebservicePort.

Change the Port and Binding names

Change the Port and Binding names

Last, click on ‘Generate Binding Content…’. In the Popup, select the option to ‘Overwrite existing binding information’

Generate Binding Content options

Generate Binding Content options

Click on the problems tab. The only Warning this should generate is the message:

WS-I: (BP2406) The use attribute of a soapbind:body, soapbind:fault, soapbind:header and soapbind:headerfault does not have value of 'literal.

You can solve this by selecting the source tab. Scroll to the section with the yellow warning symbol next to it. In here you will see:

<soap:body use='literal' namespace='ZeroWebservice' />

Change it to:

<soap:body use='literal' namespace='tns:ZeroWebservice' />

This adds in the prefix you set up when creating the project. For some reason this wasn’t added automatically. This is the solution.

If you want to see what the Source looks like for your new WSDL click on the source tab. It should look similar to this:

<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<wsdl:definitions xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns:tns='tns:ZeroWebservice' xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/' xmlns:xsd='http://www.w3.org/2001/XMLSchema' name='ZeroWebservice' targetNamespace='tns:ZeroWebservice'>
<wsdl:message name='sayHelloWorldRequest'>
<wsdl:part name='input' type='xsd:string'/>
</wsdl:message>
<wsdl:message name='sayHelloWorldResponse'>
<wsdl:part name='result' type='xsd:string'/>
</wsdl:message>
<wsdl:portType name='ZeroWebservicePort'>
<wsdl:operation name='sayHelloWorld'>
<wsdl:input message='tns:sayHelloWorldRequest'/>
<wsdl:output message='tns:sayHelloWorldResponse'/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name='ZeroWebserviceBinding'
type='tns:ZeroWebservicePort'>

<soap:binding style='rpc'
transport='http://schemas.xmlsoap.org/soap/http' />
<wsdl:operation name='sayHelloWorld'>
<soap:operation soapAction='tns:ZeroWebservice/sayHelloWorld' />
<wsdl:input>
<soap:body use='literal' namespace='tns:ZeroWebservice' />
</wsdl:input>
<wsdl:output>
<soap:body use='literal' namespace='tns:ZeroWebservice' />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name='ZeroWebservice'>
<wsdl:port binding='tns:ZeroWebserviceBinding' name='ZeroWebservicePort'>
<soap:address location='http://www.syntaxtechnology.com/WebServiceTutorial/ZeroWebservice.wsdl'/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

Configuring the Server

We are getting closer. The next thing we need to do (and it only needs to be done one time and then never again for new Web Servers) is enable the PHP SOAP functions. The easiest way to do this is to actually install them. On a Red Hat based system this is done by:

yum install php-soap

After this is done, we restart Apache.

service httpd restart

You now have your PHP SOAP extensions installed.

PHP Web Service (The Actual Code behind the WSDL – ZeroWebservice.php)

With that, we are ready to code the PHP portion of the code.

For this one, the code is very simple:

We begin with:

ini_set('soap.wsdl_cache_enabled', '0'); // disabling WSDL cache

This line disables caching the WSDL. When you have finished your code and WSDL, you want to change the “0” to a “1”. It will save the server bandwidth as it won’t have to parse the WSDL each time. However, for testing purposes you want to disable caching or you will find your changes don’t take effect immediately.

The next three lines set up the Web server itself.

$server = new SoapServer('ZeroWebservice.wsdl');
$server->addFunction('sayHelloWorld');
$server->handle();

Line 1 tells us where the WSDL is located. In this case, both the server code and the WSDL are in the same location. Line 2 registers the functions from the WSDL with the Web Service and allows them to be accessible to clients. This needs to be an array if you have more than one function. Don’t worry about this right now. It will be demonstrated in a later tutorial. The last line sets the server up to process incoming requests. It is required.

Finally, we get to the function(s). In this case, we registered one function (Line 2 from the code block above). That means we need to set up a function with the same name. Additionally, when we were creating the WSDL we made the output parameter – “result” – a string, meaning this function needs to return a string.

function sayHelloWorld($string)
{
return 'Hello World!';
}

The entire server code for ZeroWebservice.php is:

<?php
ini_set('soap.wsdl_cache_enabled', '0'); // disabling WSDL cache
$server = new SoapServer('ZeroWebservice.wsdl');
$server->addFunction('sayHelloWorld');
$server->handle();

function sayHelloWorld($string)
{
return "Hello World and " . $string . "!";
}
?>

That’s it. Short and sweet.

Web Service Client Code (ZeroWebserviceClient.php)

To test our web service and to show how an end user would access your system with a PHP Web Service call we have the code below:

<?php
ini_set('soap.wsdl_cache_enabled', '0'); // disabling WSDL cache
$client = new SoapClient("http://www.syntaxtechnology.com/WebServiceTutorial/ZeroWebservice.wsdl");
$return = $client->sayHelloWorld('User');
print_r($return);
?>

This code is very simple, it disables caching of the WSDL (you would change this to “1” again after you have finished testing), it creates a new SoapClient and gets the WSDL. Finally, it calls the sayHelloWorld() function and stores the response in the $return variable. Print out the variable and see your Web Service response.

Now you will upload all three files to your webserver (in the path you specified when creating the WSDL). Test your Web Service by accessing ZeroWebserviceClient.php. It should return Hello World! Others can now build off your (limited) web service as well by accessing your WSDL.

Here is our client in action:  ZeroWebserviceClient.php

Here is our WSDL: ZeroWebservice.wsdl

Next in the series will be acting on input parameters and adding a little functionality to your web service.