简体   繁体   中英

PHP SOAP : How can I return objects from PHP using SOAP?

I need to send/return objects or array to/from PHP using SOAP. Any good links?

I am using Zend_Soap_Server и Zend_Soap_Client. I send/receive array of difficult structure.

At first create class with structure you want to receive.

<?php

/**
 * Information about people
 */
class PeopleInformation
{
    /**
     * Name of ...
     *
     * @var string
     */
    public $name;

    /**
     * Age of
     * @var int
     */
    public $age;

    /**
     * Array of family
     *
     * @var FamilyInformation[]
     */
    public $family;
}

/**
 * Information about his family
 */
class FamilyInformation
{
    /**
     * Mother/sister/bro etc
     *
     * @var string
     */
    public $relation;

    /**
     * Name
     * @var string
     */
    public $name;
}

?>

Then create service to receive this data:

<?php

/**
 * Service to receive SOAP data
 */
class SoapService
{
    /**
     *
     * @param PeopleInformation $data
     * @return string
     */
    public function getUserData($data)
    {
        //here $data is object of PeopleInformation class


        return "OK";
    }
}
?>

Now create Zend_Soap_Server instance in controller by url http://ourhost/soap/ :

<?php

//disable wsdl caching
ini_set('soap.wsdl_cache_enabled', 0);
ini_set('soap.wsdl_cache', 0);

$wsdl = $_GET['wsdl'];

//this generate wsdl from our class SoapService
if (!is_null($wsdl))
{
    $autodiscover = new Zend_Soap_AutoDiscover('Zend_Soap_Wsdl_Strategy_ArrayOfTypeSequence');
    $autodiscover->setClass('SoapService');
    $autodiscover->handle();
}
//handle all soap request
else
{
    $wsdlPath = 'http://ourhost/soap/?wsdl';

    $soap = new Zend_Soap_Server($wsdlPath, array(
        'cache_wsdl' => false
    ));
    $soap->registerFaultException('Zend_Soap_Server_Exception');
    $soap->setClass('SoapService');
    $soap->handle();
}

?>

And now you get wsdl (http://ourhost/soap/?wsdl) with you structure and handle request in SoapService::getUserData . Input parametr in this method is object of PeopleInformation class

Basically you need to create a class map and pass it to your soap client. Yes it is a pain. I usually just have a method that maps the Soap Object name to PHP objects (ie Person => MY_Person ) and only code the ones I need to by hand (ie createdOn => DateTime ).

class MY_WSHelper
{  
  protected static $ws_map;  
  public static function make_map()
  {
    if( ! self::$ws_map)
    {
      self::$ws_map = array();
      //These will be mapped dynamically
      self::$ws_map['Person'] = NULL;
      self::$ws_map['Animal'] = NULL;
      //Hard-coded type map
      self::$ws_map['createdOn'] = DateTime;
      self::$ws_map['modifiedOn'] = DateTime;

      foreach(self::$ws_map as $soap_name => $php_name)
      {
        if($php_name === NULL)
        {
          //Map un-mapped SoapObjects to PHP classes
          self::$ws_map[$soap_name] = "MY_" . ucfirst($soap_name);
        }
      }
    }
    return self::$ws_map;
  }
}

Client:

$client = new SoapClient('http://someurl.com/personservice?wsdl',
  array('classmap' => MY_WSHelper::make_map()));

$aperson = $client->getPerson(array('name' => 'Bob'));  
echo get_class($aperson); //MY_Person  
echo get_class($aperson->createdOn); //DateTime

http://php.net/manual/en/soapclient.soapclient.php

Papa Google points me to this Zend article with lots of good examples on both the client and server aspects of working with Soap (in particular PHP5's implementation of it). Looks like a good starting point.

If you're somewhat like me, and cringe at the thought of writing up a WSDL by hand, I'd recommend using WSHelper , which uses PHP's reflection classes to dynamically generate a WSDL for you. Definitely a time-saver

I replay to share my (bad) experience.

I've created a webservice using PHP ZendFramework2 (ZF2).

The server reply objects and array of objects, and until it taken string as input it worked well. I was using the ArrayOfTypeComplex strategy.

$_strategy = new \Zend\Soap\Wsdl\ComplexTypeStrategy\ArrayOfTypeComplex();

When I try to use an array of string as input I felt in a dark and unhappy valley until I found Ramil's answer, so I change strategy and all work right!

$_strategy = new \Zend\Soap\Wsdl\ComplexTypeStrategy\ArrayOfTypeSequence();

if (isset($_GET['wsdl'])) {
    $autodiscover = new \Zend\Soap\AutoDiscover($_strategy);
    $autodiscover->setBindingStyle(array('style' => 'document'));
    $autodiscover->setOperationBodyStyle(array('use' => 'literal'));
    $autodiscover->setClass('Tracker\Queue\Service')
        ->setUri($_serverUrl);
    echo $autodiscover->toXml();
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM