weilah
weilah

Reputation: 483

Send a php complex type array via SOAP using Zend Lib and retrieving it with Android KSOAP2 client

I'm trying to return an associative array in a PHP function. This function retrieves some data from MySQL and is published in a WebService using Zend Library.

This function looks like:

Functions.php

class Functions  
{
    /** 
    *
    * @return array 
    */  
    public function Function1()  
    {

        $con = new mysqli(server, user, pass, database);

        if ($con->connect_errno) {
            die(__FUNCTION__ . $con->connect_error);
        }


        $con->set_charset('utf8');
        $arrayRet = array();

        $query = 'select field1, field2, field3 from table1';

        if(!$result = $con->query($query)){
            die(__FUNCTION__ . $con->error);
        }

        while( $row = $result->fetch_array(MYSQLI_ASSOC) )
            $arrayRet[] = $row;

        $result->close();
        $con->close(); 

        return $arrayRet;

    }
}

Then I have another PHP file that lets me access the function via SOAP (using Zend Lib):

Server.php

<?php
  include 'Zend/Soap/AutoDiscover.php';  
  include 'Zend/Soap/Server.php';  
  include 'Functions.php';  

  if(isset($_GET['wsdl']))   
  {  
     $autodiscover = new Zend_Soap_AutoDiscover();  
     $autodiscover->setClass('Functions');  
     $autodiscover->handle();  
  }   
  else   
  {  
     $server = new Zend_Soap_Server("http://localhost/webservice/Server.php?wsdl");  
     $server->setClass('Functions');  
     $server->handle();  
  }  
?>

So far everything looks quite normal. If i write a php client, i'm able to consume the webservice and access the returned array as follows:

<?php

$client = new Zend_Soap_Client('http://localhost/webservice/Server.php?wsdl');
$arrayRet = $client->Function1();

foreach($arrayRet as $row )  
{  
 ?>
    <b>Field1: </b><?php echo $row['field1']; ?><br>
    <b>Field2: </b><?php echo $row['field2']; ?><br>
    <b>Field3: </b><?php echo $row['field3']; ?><br>
<?php  
  }  
?>

Ok, now my problem is that i'm not writing a php client but a Android client. I'm using the ksoap2 library to achieve it. With this library i'm able to handle "normal arrays" with the pare key and value, following this algorithm. Using his properies:

    SoapObject category_list = (SoapObject) property;
    String key = category_list.getProperty("key").toString();
    String value = category_list.getProperty("value").toString();

But the response from the function above (if i copy the toString() result) looks like:

Function1Response
{
  return=
  [
   Map{
    item=anyType{key=field1; value=hello; }; 
    item=anyType{key=field2; value=web; }; 
    item=anyType{key=field3; value=service; };}, 

   Map{
    item=anyType{key=field1; value=hello2; }; 
    item=anyType{key=field2; value=web2; }; 
    item=anyType{key=field3; value=service2; };}, 

   Map{
    item=anyType{key=field1; value=hello3; }; 
    item=anyType{key=field2; value=web3; }; 
    item=anyType{key=field3; value=service3; };}
   ]; 
  }

I could iterate this response using key and value properties, but i think it would be much better (and efficient) if i could have a response like:

Function1Response
{
  return=
  [
   Map{
    item=anyType{field1=hello; }; 
    item=anyType{field2=web; }; 
    item=anyType{field3=service; };}, 

   Map{
    item=anyType{field1=hello2; }; 
    item=anyType{field2=web2; }; 
    item=anyTypefield3=service2; };}, 

   Map{
    item=anyType{field1=hello3; }; 
    item=anyType{field2=web3; }; 
    item=anyType{field3=service3; };}
   ]; 
  }

So i could retrive them like:

    SoapObject category_list = (SoapObject) property;
    String field1 = category_list.getProperty("field1").toString();
    String field2 = category_list.getProperty("field2").toString();
    String field3 = category_list.getProperty("field3").toString();

Is that possible? I think it can be done somehow in the php server side. But i have no idea. I have been reading here and there but nobody seems to have this problem.. or a solution.

I'm sorry for the long post. I could give more code details or explain it better if i've been not clear enough.

Thanks for helping!

Upvotes: 0

Views: 2645

Answers (1)

weilah
weilah

Reputation: 483

Well, i did find the solution.

The function in the PHP server that will publish the result in the webservice looks like:

class Functions  
{
    /** 
    *
    * @return array 
    */  
    public function Function1()  
    { 

        $con = new mysqli(server, user, pass, database);

        if ($con->connect_errno) {
            die(__FUNCTION__ . $con->connect_error);
        }


        $con->set_charset('utf8');
        $arrayRet = array();

        $query = 'select field1, field2, field3 from table1';

        if(!$result = $con->query($query)){
            die(__FUNCTION__ . $con->error);
        }

        while( $row = $result->fetch_array(MYSQLI_ASSOC) ){
            $myClass = new TestClass();
            $myClass->field1 = $row["field1"];
            $myClass->field2 = $row["field2"];
            $myClass->field3 = $row["field3"]; 
            array_push($arrayRet, $myClass);
        }


        $result->close();
        $con->close(); 

        return $arrayRet;

    }
}

I have previously created a class with all relevant attributes, as simple as:

TestClass.php

<?php
class TestClass 
{
    /**
    * @var string 
    */
    public $field1;

    /**
    * @var string 
    */
    public $field2;

    /**
    * @var string 
    */
    public $field3;

}

?>

So basically we're returning an array filed with all the different instances of this class as items.

Now, in the Android Client Side (always using ksoap2 library) i receive a response like:

Function1Response
{
  return=
  [
    Struct{field1=hello; field2=web; field3=service;  },
    Struct{field1=hello2; field2=web2; field3=service2; }, 
    Struct{field1=hello3; field2=web3; field3=service3;}
  ]; 
}

and i'm able to iterate it:

        //call
        androidHttpTransport.call(SOAP_ACTION, envelope);

        //envelope response
        SoapObject result = (SoapObject) envelope.bodyIn;

        //retrieve the first property, actually the array
                Vector result3 = (Vector) result.getProperty(0);

        //iterate
        Enumeration e=result3.elements(); e.hasMoreElements();)
        {
            //each object from the array its an Soap Element that contanins the properties defined in the php class
            SoapObject item=((SoapObject)e.nextElement());

            String field1 = item.getProperty("field1").toString();
            String field2 = item.getProperty("field2").toString();
            String field3 = item.getProperty("field3").toString();

            stringBuilder.append(
                    "Field1: " + codi + "\n"+ 
                    "Field2: "+ titol +"\n"+ 
                    "Field3: "+ descr +"\n"+
                    "******************************\n");
        }

And that's it... i hope it will be useful for someone else. Thanks

Upvotes: 2

Related Questions