PHP: Exposing web services - Part 1



Web services are useful for a number of things, e.g. we can provide companies with data without needing to give them direct access to our databases.

One of the most important uses (in my opinion) is the interoperability it provides, which allows different platforms, devices etc to interact with each other.

In this post we're going to expose a web service in PHP using NuSphere's Soap library, which has been in development since 2002 - which like the name suggests relies on the SOAP protocol (XML based) and consume it in a C# application using WCF.

First of all you will need to include the library and instantiate a new soap_server object, like this:
 
include "lib/nusoap.php";
 
$namespace = "http://www.cstruter.com";
$server = new soap_server();
$server->soap_defencoding = 'UTF-8';
$server->configureWSDL("TestService", $namespace);
$server->wsdl->schemaTargetNamespace = $namespace;
 

It's quite important to set our soap_defencoding property to UTF-8, since this is the default encoding required by the WCF (Windows Communication Foundation)

We also need to register the functions we wish to expose against our soap_server object, like so:
 
$server->register('test', // function name
				array("name"=>"xsd:string"),  // parameters
				array('return'=>'xsd:string'), // return value type
				$namespace);
 
function test($name)
{
	return "Hello $name";
}
 
 

Once we're done, we tell our object to handle actions sent to our script like this:
 
$POST_DATA = isset($GLOBALS['HTTP_RAW_POST_DATA']) 
				? $GLOBALS['HTTP_RAW_POST_DATA'] 
					: @file_get_contents("php://input");
 
$server->service($POST_DATA);
 

On the C# side (using Visual Studio 2008/10), right click on your project and click on Add Service Reference.


Notice the querystring "?wsdl" circled in the image above, passed along with the url to the reference, this tells the NuSoap library to output WSDL (Web Services Description Language) - which provides C# with all the information it needs to consume the web service (something I will discuss in the next part of this post).

Using the web service in C# looks something like this:
 
using System;
using cstruter.com.Service; // Namespace defined in the Add Service Reference dialog
 
namespace cstruter.com
{
    class Program
    {
        static void Main(string[] args)
        {
            TestServicePortTypeClient TestService = new TestServicePortTypeClient();
            String value = TestService.test("Julie");
            Console.WriteLine(value); // Outputs Hello Julie
        }
    }
}
 

Now thats pretty much the basics to get us up and running, but what If we want to do a bit more? Like passing/returning objects from/to the web service, we need to define types, like this:
 
$server->wsdl->addComplexType(
    'post',				// Name of the object
    'complexType',		// Object Type (Why? Since we've got an addSimpleType method?)
    'struct',			// Struct /Array (Multiple objects)
    'all',				// Composition
    '',					// Restriction Namespace
    array(
        'postID' => array('name' => 'postID', 'type' => 'xsd:int'),
        'Title' => array('name' => 'Title', 'type' => 'xsd:string'),
		'Body' => array('Body' => 'Body', 'type' => 'xsd:string')
    ) // Structure Defintion
);
 

Using the new defined object is very straightforward e.g. "tns:post":
 
$server->register('test2', 
					array("name"=>"tns:post"), 
					array('return'=>'xsd:string'), 
					$namespace);
 
function test2($value)
{
	return print_r($value, true);
}
 

On the C# side of things you will notice an auto-generated version of the object (post) we defined in our PHP script becomes available:
 
TestServicePortTypeClient TestService = new TestServicePortTypeClient();
post p = new post
{
    postID = 1,
    Title = "Test 1 2 3",
    Body = "Some test"
};
 
String value = TestService.test2(p);
Console.WriteLine(value);
 

If we wish to pass an array of objects e.g. post[], we need to add another complexType.
 
$server->wsdl->addComplexType(
	'posts', 			// Name of the object
	'complexType',		
	'array',			// Array since we're passing a set of objects
	'', 
	'SOAP-ENC:Array',
	array(),
	array(
		array('ref' => 'SOAP-ENC:arrayType', 'wsdl:arrayType' => 'tns:post[]')
	),
	'tns:post' // Child object
);
 

In the next snippet we pass an array of posts to the web service:
 
$server->register('test3', 
					array(), // Blank array if we don't have any parameters.
					array('return'=>'tns:posts'), // The array of objects.
					$namespace);
 
function test3()
{
	return array(array('postID'=>1, 
						'Title'=>'test 1', 
						'Body'=>'abc abc abc'), 
				 array('postID'=>2, 
						'Title'=>'test 2', 
						'Body'=>'123 123 123')
	);
}
 

And this is how we retrieve the array via C#:
 
TestServicePortTypeClient TestService = new TestServicePortTypeClient();
post[] ps = TestService.test3();
foreach (post p in ps)
{
    Console.WriteLine(String.Concat(p.postID, ":", p.Title, ":", p.Body));
}
 

In conclusion I feel its quite a nice, simple to use library written by the guys at NuSphere. There is quite a bit more to this library, but these examples should get you on your way.

In the next part of this post we're going to have a look at the SoapServer php extension.







Comments



Thanks.


mr

thanks for the excellent explanation. :)


Post comment

Name *
Email
Title
Body *
Security Code
*
* Required fields

Related Posts

Latest Posts

Be the best stalker you can be


2011-12-13 22:33:54

Syntactic sugar (C#): Enum


2011-08-04 16:50:18

Top 5 posts

Simple WYSIWYG Editor


Creating a WYSIWYG textbox for your website is actually quite simple.
2007-02-01 12:00:00

Moving items between listboxes in ASP.net/PHP example


Move items between two listboxes in ASP.net(C#, VB.NET) and PHP
2008-06-12 17:07:43

Cross Browser Issues: Firefox Word Wrapping


Firefox word wrapping issues
2008-06-09 09:51:21

Populate a TreeView Control C#


Populate a TreeView control in a windows application.
2009-08-27 16:01:03

C# YouTube : Google API


Post on how to integrate with YouTube using the Google Data API
2011-03-12 08:37:51