Menu:

Sponsor

Discover Master of Alchemy, our first iPad/iPhone and iPod touch game!

 

Forum's topics

Latest Files

Archives

Top Rated

Categories

Photo Gallery


Create a WebService with PEAR::SOAP

Introducing.

PHP has various ways in which you can implement Web services, including NuSOAP, PHP-SOAP, and PEAR .
In this tutorial we will see how it's easy to create a webService using PEAR.

1. What you need

PEAR is not a standalone PHP application, but a complex framework for building quite every application with PHP.
PEAR download and installation

To begin, you need an Apache with PHP.
Depending on the PHP version you have installed, you may still need to download the PEAR Package Manager, which is in charge of administering all of PEAR's modules and functionality.
Once you have installed the PEAR Package Manager you can proceed to installing the necessary PEAR modules for using SOAP in PHP by using the pear install [Module_Name] command.
If you execute this command while you have an active connection to the Internet, it will automatically download and install the module in your local environment. If you don't have an active connection, you will need to download the SOAP package for PEAR as well as some prerequisite PEAR modules from http://pear.php.net/packages.php in order to install the SOAP package, including Mail_Mime, Net_URL, HTTP_Request, and Net_DIME.

Now we are ready.

1.1 Our Goal.

Our goal is obviously to create a WebService, and then maybe consume it using Flash.. but what our WS will do?
The WebService we are going to create will do the calculation in order to find paths from a given grid. This path finder will be based on the A* algorithm and can be useful when clients such as flash have poor math capabilities and they can crash with calculations on large grids. For this reason we will pass the hard job to the server machine, and in this case to PHP.
This is the WSDL representation of the Web Service once completed:
http://www.sephiroth.it/webservices/pathfinder_server.php?wsdl

 

1.2 The Path Finder Algorithm (with A*)

In this tutorial I will not explain all the parts of the path finder A* algorithm because i would like to focus the attention to the PEAR SOAP part. In order to understand the A* I suggest you to read first this tutorial, in which I explain the path finder with Flash (the PHP is the same of flash, just translated into PHP code)

 

2. The PHP class

Now, create a new PHP file "pathfinder_server.php" with these lines of code (i will explain later, step by step):


<?php
/**
    Be sure you've both PEAR installed on your web server
    and that all the required PEAR modules have been installed
*/
require_once('SOAP/Server.php');
require_once(
'SOAP/Disco.php');

/**
* @class StructNode 
* @description Create an object for register the values of every map item
*/
class StructNode
{
    var 
$pos = array();
    var 
$f = -1;
    var 
$g = -1;
    var 
$h = -1;
    var 
$parent "undefined";
    var 
$pos_str "";
    
/* constructor */

    
function StructNode($pos$f$g$h)
    {
        
$this->pos $pos;
        
$this->$f;
        
$this->$g;
        
$this->$h;
        
$this->pos_str implode($this->pos,",");
    }
    
    
/* convert into string repr */
    
function toString (){
        return 
"[" $this->pos_str "], f=" $this->", g=" $this->", h=" $this->h;
    }    
}

/**
* @class PathFinder
*/
class PathFinder
{
    var 
$__dispatch_map = array();
    var 
$__typedef = array();
    var 
$__openList = array();
    var 
$__closedList = array();
    var 
$map;
    var 
$fp;    
    
/** 
    * class constructor 
    * define all the methods for this class and their arguments/returns type
    * this is necessary for the wsdl calls
    */
    
function PathFinder()
    {
        
// define operation name (initialize)
        // its parameters (in)
        // the return object (out)
        
$this->__dispatch_map['initialize'] = array(
            
"in"  => array("map"  => "{urn:PathFinder}ArrayOfStrings"),
            
"out" => array("code" => "string")
        );
        
$this->__dispatch_map['findPath'] = array(
            
"in"  => array("sid"  => "string""startPosition" => "string""endPosition" => "string"),
            
"out" => array("code" => "{urn:PathFinder}ArrayOfStrings")
        );        
        
$this->__typedef['ArrayOfStrings'] = array(array('item'=>'string'));
    }
    
    
/* init grip map */
    
function initialize($map)
    {
        
session_start();
        
$ar = array();
        foreach(
$map as $value){
            
$new_value explode(","$value);
            
/* int conversion */
            
while(list($key,$val) = each($new_value)){
                
$new_value[$key] = intval($val);
            }
            
$ar[] = $new_value;
        }
        
$this->map $ar;
        
$_SESSION['map'] = $ar;
        return 
session_id();
    }    
    
    
    
/**
    * @method findPath
    * @description find the right path in order to move the cursor from the starting pos to the end position
    * @param $sid String session id
    * @param $startPosition ArrayOfStrings starting point
    * @param $endPosition ArrayOfStrings end position
    * @returns ArrayOfString Array of positions
    */
    
function findPath($sid$startPosition$endPosition)
    {
        
session_id($sid);
        
session_start();
        
$startPosition explode(",",$startPosition);
        
$endPosition explode(",",$endPosition);
        while(list(
$k,$v) = each($startPosition)){
            
$startPosition[$k] = intval($v);
        }
        while(list(
$k,$v) = each($endPosition)){
            
$endPosition[$k] = intval($v);
        }
        
$end_pos_str implode($endPosition",");
        
$result = array(); // the array with the positions
        
$result_str = array(); // the array with the positions strings
        
$this->__openList = array();
        if(!empty(
$_SESSION['map']))
        {
            
$startingNode = new structNode ($startPosition000);
            
$this->__openList[] = $startingNode;
            while (
count($this->__openList) > 0) {
                
$max 5000;
                
$sel = -1;
                for (
$a 0$a count($this->__openList); $a++) {
                    if (
$this->__openList[$a]->$max) {
                        
$max $this->__openList[$a]->f;
                        
$sel $a;
                    }
                }
                
$node array_splice($this->__openList$sel1);
                
$node $node[0];
                if (
$node->pos_str == $end_pos_str) {
                    
$this->__closedList[] = $node;
                    
$cur $this->__closedList[count($this->__closedList) - 1];
                    while(
$cur->parent != "undefined"){
                        
$result[] = $cur;
                        
$result_str[] = $cur->pos_str;
                        
$cur $cur->parent;
                    }
                    return 
array_reverse($result_str);
                }
                
$succ $this->getSuccessors ($node->pos);                
                for (
$a 0$a count($succ); $a++) {
                    
$_skip false;
                    
$struct = new structNode ($succ[$a],0,0,0);
                    
$struct->parent $node;
                    
$struct->$node->$this->getDistance ($struct->pos$node->pos);
                    
$struct->$this->getDistance ($struct->pos$endPosition);
                    
$struct->$struct->$struct->h;
                    foreach (
$this->__openList as $b => $value) {
                        if (
$this->__openList[$b]->pos_str == $struct->pos_str && $this->__openList[$b]->$struct->f) {
                            
$_skip true;
                            break;
                        }
                    }
                    foreach (
$this->__closedList as $b => $value) {
                        if (
$this->__closedList[$b]->pos_str == $struct->pos_str && $this->__closedList[$b]->$struct->f) {
                            
$_skip true;
                            break;
                        }
                    }
                    
// TODO //
                    
if ($_skip == false) {
                        for(
$c 0$c count($this->__openList); $c++){
                            if (
$this->__openList[$c]->pos_str == $struct->pos_str) {
                                
array_splice($this->__openList$c1);
                            }
                        }
                        for(
$c 0$c count($this->__closedList); $c++){
                            if (
$this->__closedList[$c]->pos_str == $struct->pos_str) {
                                
array_splice($this->__closedList$c1);
                            }
                        }                        
                        
array_push($this->__openList$struct);
                    }
                }
            
array_push($this->__closedList$node);
            }            
            return 
$result;
        } else {
            return array();
        }
    } 
    
    
/**
    * @method getSuccessor private
    * @description get the 8 successor by position
    */
    
function getSuccessors ($pos)
    {
        
$r intval($pos[0]);
        
$c intval($pos[1]);
        
$ret = array ();
        if (isset(
$_SESSION['map'][$r 1][$c]) and $_SESSION['map'][$r 1][$c] == 0) {
            
$ret[] = array($r 1$c);
        }
        if (isset(
$_SESSION['map'][$r][$c 1]) and $_SESSION['map'][$r][$c 1] == 0) {
            
$ret[] = array($r$c 1);
        }
        if (isset(
$_SESSION['map'][$r 1][$c]) and $_SESSION['map'][$r 1][$c] == 0) {
            
$ret[] = array($r 1$c);
        }
        if (isset(
$_SESSION['map'][$r][$c 1]) and $_SESSION['map'][$r][$c 1] == 0) {
            
$ret[] = array($r$c 1);
        }
        return 
$ret;
    }
    
/**
    * @method getDistance private
    * @description get the distance between 2 positions
    */
    
function getDistance ($pos1$pos2)
    {
        
$d1 abs($pos2[0] - $pos1[0]);
        
$d2 abs($pos2[1] - $pos1[1]);
        return (
$d1 $d2);
    }    
}


/**
* Initialize the SOAP server
*/
$server = new SOAP_Server();

// initialize the pathfinder class
$webservice = new PathFinder();

// set the path finder class as default responder for the WSDL class
$server->addObjectMap($webservice,'http://schemas.xmlsoap.org/soap/envelope/');

// start serve
if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD']=='POST') {
     
$server->service($HTTP_RAW_POST_DATA);
} else {
     
$disco = new SOAP_DISCO_Server($server,'PathFinder');
     
header("Content-type: text/xml");
     if (isset(
$_SERVER['QUERY_STRING']) && strcasecmp($_SERVER['QUERY_STRING'],'wsdl') == 0) {
         
// show only the WSDL/XML output if ?wsdl is set in the address bar
         
echo $disco->getWSDL();
     } else {
         echo 
$disco->getDISCO();
     }
}
exit;
?>