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.
Posted by - Christoff Truter
Date - 2010-05-06 22:30:42
Comments
Post comment