PEAR Forum :: PHP Extension and Application Repository

PEAR Forum Forum Index
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister   ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
Does anybody know how to describe a complex type n SOAP?

 
Post new topic   Reply to topic    PEAR Forum Forum Index -> Web Services
View previous topic :: View next topic  
Author Message
hujuice



Joined: 07 Apr 2007
Posts: 1

PostPosted: Sat Apr 07, 2007 6:21 pm    Post subject: Does anybody know how to describe a complex type n SOAP? Reply with quote

The more exact question is:
źDoes anybody know how to describe a complex type building a SOAP server with PEAR?╗

Normally, I can describe types by this:
Code:

public function __construct($conn) {
             // Define the signature of the dispatch map on the Web services method and connect to DB
             
             // DB connection
             $this->conn = $conn;
             
             // Necessary for WSDL creation
             $this->__dispatch_map['getAS'] = array (
                                                    'in' => array('code' => 'integer'),
                                                    'out' => array('as' => 'array')
                                                    );
      }

But the resulting outputted array is always an array of strings. I need, instead, a more complex array (an indexed array of strings, with integer "random" inexes).

How to describe it?

HUjuice
Back to top
View user's profile Send private message
dninja



Joined: 20 Apr 2007
Posts: 2

PostPosted: Mon Apr 23, 2007 4:28 pm    Post subject: Reply with quote

This will define a function which takes and returns a complex type

Code:
        $this->__dispatch_map['do_it2'] = array(
            "in" => array ("inp" => "{urn:PathFinder}Test"),
            "out" => array ("outp" => "{urn:PathFinder}Test")
        );

        $this->__typedef['Test'] = array(
                                        "item" => 'string',
                                        "item2" => "string",
                                        "number" => "int",
                                        ); 


The problem I'm having is returning an array of them to C#. If I define:

Code:


        $this->__dispatch_map['array_test'] = array(
            "in" => array ("inp" => "{urn:PathFinder}ArrayOfTests"),
            "out" => array ("outp" => "{ur:PathFinder}ArrayOfTests")
        );


        $this->__typedef['ArrayOfTests'] = array(array('item'=>'{urn:PathFinder}Test'));


The array of strings goes in ok but I can't get the array back out, even if I pass out exactly what I passed in!

If anyone knows how to get an array out I'd be happy!
Back to top
View user's profile Send private message
leon



Joined: 04 May 2007
Posts: 3

PostPosted: Fri May 04, 2007 5:31 pm    Post subject: Reply with quote

I have exactly the same problem (I think). I've tried this with an adapted version of the code shown here:
http://www.sephiroth.it/tutorials/flashPHP/WebServicePEAR/index.php
(See below for exact code)
When I try to use this from a C# client then the function returns NULL instead of an array.
If anyone reading this has the answer or knows the reason, please let me/us know.

Code:

<?php
/*require_once PATH TO FILE THAT SETS THE PATH OF THE PEAR REPOSITORY;*/
require_once('SOAP/Server.php');
require_once('SOAP/Disco.php');

/**
* @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['findPath'] = array(
            "in"  => array("sid"  => "string", "startPosition" => "string", "endPosition" => "string"),
            "out" => array("code" => "{urn:PathFinder}ArrayOfStrings")
        );       
        $this->__typedef['ArrayOfStrings'] = array(array('item'=>'string'));
    }
   
    /**
    * @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)
    {
        return array("first", "second");
    }
}



/**

* 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;

?>
Back to top
View user's profile Send private message
dninja



Joined: 20 Apr 2007
Posts: 2

PostPosted: Fri May 04, 2007 5:47 pm    Post subject: Reply with quote

I gave up and used a web services call to create a csv file then a wget to grab the file which I then parsed. A complete cop-out from using web services correctly but hey, it worked!

I would like ot know how to do this correctly though.
Back to top
View user's profile Send private message
leon



Joined: 04 May 2007
Posts: 3

PostPosted: Wed May 09, 2007 3:56 pm    Post subject: Reply with quote

I also gave up after wasting a day on trying to do this. I have actually considered creating a _very_ simple php soap library that mimics the behavior of a C# soap server, but decided that that was too much effort.

I want to use serialization now, but i'm debating if I want to:
- create my own serialize function in php and unserialize in C#
- use the built in PHP one (http://nl2.php.net/manual/en/function.serialize.php ) together with a custom built C# unserialize to match.
- Use JSON libraries for both PHP and C# (http://www.json.org/ ).
- ... (still thinking, so other stuff might still occur to me)
Back to top
View user's profile Send private message
leon



Joined: 04 May 2007
Posts: 3

PostPosted: Fri May 11, 2007 5:24 pm    Post subject: Reply with quote

Okay, I didn't use serialization. I stuck with it, and I found a solution.

Instead of doing just
Code:
return array("first", "second");
, i do the following:
Code:

return new SOAP_Value("result",
                      false,
                      array(
                        new SOAP_Value("Item", false, "first"),
                        new SOAP_Value("Item", false, "second"),
                        new SOAP_Value("Item", false, "third")
                      ),
                      array(
                        "SOAP-ENC:arrayType" => "xsd:int[3]"
                      ));

Be sure not to forget the
Code:
"SOAP-ENC:arrayType" => "xsd:int[3]"
part, this is where the .NET client fails. It wants to know exactly how may elements are in the array you return (and of what type they are). See also this page where I found this:
Quote:
The PHP and PEAR_SOAP version is somewhat uncomfortable. But I will show you the tricky part of a dotNet-valid soap response.

<Users xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soap-enc:Array" soap-enc:arrayType="auth:User[2]">

Have a look at the last attribute holding the 'soap-enc' namespace. Figuring out that dotNet xml-serializer needs the exact size of the response array took us several hours.


This does not result in correct code however. There seems to be a bug in PEAR::SOAP (I am using 0.10.1). The above will result in XML being sent not with:
Code:
<result SOAP-ENC:arrayType="xsd:string[3]">

but with
Code:
<result SOAP-ENC:arrayType="xsd:string">

which is obviously incorrect.
If you open Base.php in your PEAR::SOAP library, comment out the the part of code at line 1242, this solved it for me.
Code:

/*
// A little more magic than should be in a qname.
$p = strpos($this->name, '[');
if ($p) {
    // TODO: Need to re-examine this logic later.
    // Chop off [].
    $this->arraySize = explode(',', substr($this->name, $p + 1, -$p - 2));
    $this->arrayInfo = substr($this->name, $p);
    $this->name = substr($this->name, 0, $p);
}*/


See also this pear bug.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    PEAR Forum Forum Index -> Web Services All times are GMT + 2 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum



PEAR Forum topic RSS feed 
Powered by phpBB © 2001, 2005 phpBB Group

Provided by Ministry of Web developement