Monday, June 22, 2009

PHP Web Services with NuSOAP

Introduction

NuSOAP is a group of PHP classes that allow developers to create and consume SOAP web services. It does not require any special PHP extensions.This document describes how to obtain and install NuSOAP, then provides some samples to illustrate the capabilities of NuSOAP. It is by no means an exhaustive description of NuSOAP, but it is hopefully enough to get any PHP coder started. Programming with NuSOAP follows this up with more complex samples.

What are Web Services

The term Web services describes a standardized way of integrating Web-based applications using the XML, SOAP, WSDL and UDDI open standards over an Internet protocol backbone. XML is used to tag the data, SOAP is used to transfer the data, WSDL is used for describing the services available and UDDI is used for listing what services are available. Used primarily as a means for businesses to communicate with each other and with clients, Web services allow organizations to communicate data without intimate knowledge of each other's IT systems behind the firewall.




Web Services Protocol Stack

The Web Services protocol stack consists of three key XML-based technologies: SOAP (Simple Object Access Protocol), WSDL (Web Service Description Language), and UDDI (Universal Description, Discovery and Integration).
UDDI: This layer is responsible for centralizing services into a common registry, and providing easy publish/find functionality. Currently, service discovery is handled via the UDDI. The UDDI specification can help to solve making it possible to discover the right services from the millions currently online. Learn more about UDDI here.
WSDL: This layer is responsible for describing the public interface to a specific Web service, which is an XML-based language that describes the various functions that a Web service is capable of. Currently, service description is handled via the WSDL. You do not need to learn all the nitty-gritty details because there are tools that generate WSDL for you. You can get one here.

SOAP: This layer is responsible for encoding messages in a common XML format so that messages can be understood at either end. Currently, this includes XML-RPC and SOAP. For example, the client program bundles up two values to be added into a SOAP message, which is sent to the Web service by sending it as the body of an HTTP POST request. The server unpacks the SOAP request that the application can understand and executes Add operation. Next, the server packages up that result of summation as response into another SOAP message, which it sends back to the client program in response to its HTTP request. The client program unpacks the SOAP message to obtain the results of the summation. So, SOAP= XML + HTTP.






Creating Nusoap

Download latest version of nusoap.php from http://sourceforge.net/projects/nusoap/

Here I am going to create a server which will take UserID as request and fetch User's details with respect to the UserID

  • Creating the user's table
CREATE TABLE `tbl_user` (
`user_id` int(11) NOT NULL auto_increment,
`user_name` varchar(30) NOT NULL default '',
`password` varchar(70) NOT NULL default '',
`first_name` varchar(100) NOT NULL default '',
`last_name` varchar(100) NOT NULL default '',
`email_id` varchar(100) NOT NULL default '',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;

  • Creating a php page to fetch record from table "tbl_user"

# Save this code a userclass.php

class Users {

function DBConnection()
{
mysql_pconnect ('HostName', 'UserName', 'PassWord') ;
mysql_select_db ('DataBaseName');
}

function getUserDetails($userid){

$this->DBConnection();
$Query = "SELECT * FROM tbl_user
where user_id = $userid";
$result = mysql_query($Query) or die(" Your ERROR CODE ");

if(!$result) {
die(" Your ERROr CODE ");
}
$cnt = 0;
$UserResultArray= array();
while ($UserResult = mysql_fetch_assoc($result))
{

// Result Array
$UserResultArray[$cnt] = array(
'UserID' => $UserResult["user_id"],
'UserName' => $UserResult["user_name"],
'FirstName' => $UserResult["first_name"],
'LastName' => $UserResult["last_name"],
'EmailID' => $UserResult["email_id"]);


$cnt = $cnt + 1;
}


return $UserResultArray;
}


}

// End of userclass.php
  • Creating Nusoap Server code
// Save this code as users.php


// Downloaded Nusoap file
require_once("nusoap.php");
// Including the created php function file
require_once("userclass.php");
// Name space name
$ns="urn:UserDetails_wsdl";
$server = new soap_server();
// Configure WSDL
$server->configureWSDL('UserDetails_wsdl', 'urn:UserDetails_wsdl');
$server->wsdl->schemaTargetNamespace=$ns;


// Creating Complex type for out put (only for single record)
$server->wsdl->addComplexType('UserDetailsRow',
'complexType','struct', 'all', '',

array( 'UserID' => array('name' => 'UserID', 'type' => 'xsd:int'),
'UserName' => array('name' => 'UserName','type' => 'xsd:string'),
'FirstName' => array('name' => 'FirstName','type' => 'xsd:string'),
'LastName' => array('name' => 'LastName','type' => 'xsd:string'),
'EmailID' => array('name' => 'EmailID','type' => 'xsd:string')
));

// Complex type for multiple record out put.
$server->wsdl->addComplexType('UserDetailsRows','complexType',
'array','','SOAP-ENC:Array',

array(),array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'tns:UserDetailsRow[]')),
'tns:UserDetailsRow');

// Registering getUserDetails function for WSDL generation
$server->register('getUserDetails', // method name
array('' => 'xsd:void'), // input parameters
array('return' => 'tns:UserDetailsRows'), // output parameters
'urn:UserDetails_wsdl', // namespace
'urn:UserDetails_wsdl#getUserDetails', // soapaction
'rpc', // style
'encoded', // use
'Fetching User details' // documentation
);

// Main function (Registered function)
function getUserDetails($userid)
{
$userClass = new Users; // Object from userclass.php
return $userClass->getUserDetails($userid);
}

//=============
// Output return
//=============
$HTTP_RAW_POST_DATA = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
$HTTP_RAW_POST_DATA = file_get_contents("php://input");
$server->service($HTTP_RAW_POST_DATA);
exit();

// End of users.php
You can access your WSDL file now using http://localhost/users.php . You will be getting below out put




  • Creating Client for Nusoap
// Save this code as getUserDetails.php

require_once('nusoap.php');
$soapclient = new soapclient('http://localhost/users.php');
$soapclient->debug_flag=true;
$err = $soapclient->getError();
$UserID = $_REQUEST["UserID"];
$param = array("UserID"=>$UserID);
$result=$soapclient->call("getUserDetails",$param);
header("Content-Type: text/xml\r\n");
echo $soapclient->responseData;

// End of getUserDetails.php

Now we can access our client using
'http://localhost/getUserDetails.php?UserID=1'
Verify the below output of newly created Nusoap XML webservice . Make sure that you are passing UserID as argument in the query string .


Now you can make your own webservices with different format .

Enjoy !!!!!!

Vineesh.



15 comments:

  1. Hi

    Esenario:
    web service: manageSession.asmx
    method: startSession(user,pswd)

    web service: manageStaff.asmx
    method: getStaff(id)

    When you consume manageSession.asmx / startSession(user,pswd) it validate and start the session in the .NET web service application.

    When you consume manageStaff.asmx / getStaff(id), first, it validate the current session, if has been started, then return the Staff.

    Problem:
    Using nusoap, I dont know where to define the same parameter of connection, because each time I create a new client I supouse they change, becouse in the manageStaff.asmx displays my programed message -you have not start session-

    The problem are not the web service becouse it was tested in .aspx pages and works.

    All the comments are wellcome

    Att:
    Ing. Jorge Andrés Cañón Sierra

    ReplyDelete
  2. I like this article as it makes things clear. I couldn't get it to work via SoapUI though, until i added the userid value to the request xml manually, or change the following input parameters line in users.php:
    array('' => 'xsd:void'), // input parameters
    into
    array('userid' => 'xsd:int'), // input parameters

    now it generates wsdl with the detail info showing
    parts:
    userid: xsd:int

    like in your example.

    Still working hard on getting this to work via the getUserDetails.php though :(

    ReplyDelete
  3. Hey i got the getUserDetails working now as well.

    i changed:
    $soapclient = new soapclient('http://localhost:8888/wstest/users.php');
    INTO
    $soapclient = new nusoap_client('http://localhost:8888/wstest/users.php?wsdl',true);

    Now things work. Don't know why you use new soapclient when working with nusoap; it seems to be creating off xml and gets parse errors like:

    Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://localhost:8888/wstest/users.php' : Premature end of data in tag html line 2 in /Applica.... etc

    hope you can change this because this can take hours to figure out for noobs like me

    thanks, EeKay

    ReplyDelete
  4. @Vineesh:Please How do i get to see the xml generated for each record search because i tried accessing the record through the url example you gave but all i see is blank page.

    ReplyDelete
  5. You cant access that URL ,I have given that as an example . Create your own using the above code and try it !!!!

    ReplyDelete
  6. XML Parsing Error: no element found
    Location: http://localhost/getUserDetails.php?UserID=1
    Line Number 1, Column 1:

    ReplyDelete
  7. thanks for this information, it helped me a lot.

    ReplyDelete
  8. Example is very helpful, my service is located in a user protected directory.

    In such a case when i accessing the server service, its giving the following error

    Fatal error: Uncaught SoapFault exception: [HTTP] Authorization Required in

    please give me a solution.

    ReplyDelete
  9. please give me a solution,
    Uncaught SoapFault exception: [Client] Function ("getMerchantDetails") is not a valid method for this service

    ReplyDelete
  10. Thanks for the explanation.
    There is an error i found.

    Warning: SoapClient::SoapClient(http://localhost/webservice1/users.php) [soapclient.soapclient]: failed to open stream: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. in D:\xampp\htdocs\webservice1\getUserDetails.php on line 3

    Warning: SoapClient::SoapClient() [soapclient.soapclient]: I/O warning : failed to load external entity "http://localhost/webservice1/users.php" in D:\xampp\htdocs\webservice1\getUserDetails.php on line 3

    Fatal error: Maximum execution time of 60 seconds exceeded in D:\xampp\htdocs\webservice1\getUserDetails.php on line 10

    ReplyDelete
  11. hello as he said earlier, I am only seeing blank pages I can't see the xml when I run getUserDetails.php?UserID = 1.
    I did all the stuff on my side and it didn't work. any help?

    ReplyDelete
  12. I like this article as its very clear...but while running it shown this error....

    Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://localhost/Getrequest/test/server.php' : Premature end of data in tag html line 2 in /opt/lampp/htdocs/Getrequest/test/client.php:3 Stack trace: #0 /opt/lampp/htdocs/Getrequest/test/client.php(3): SoapClient->SoapClient('http://localhos...') #1 {main} thrown in /opt/lampp/htdocs/Getrequest/test/client.php on line 3

    kindly clarify this

    ReplyDelete
  13. XML Parsing Error: no element found
    Location: http://localhost/Jisha/getUserDetails.php?UserID=1
    Line Number 2, Column 1:
    ^

    ReplyDelete

Followers