Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP SoapClient example using typemap option

Tags:

php

soap

I'm having a slight issue with namespace usage in PHP's SoapClient. From the documentation I believe the typemap option of the constructor will solve my issue.

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

I just haven't found a solid example of its usage.

Does someone have an example?

like image 587
Stanley.Goldman Avatar asked Jan 26 '11 16:01

Stanley.Goldman


1 Answers

Here's a simple example taken from test source with my notes added in:

The SOAP Request

<env:Envelope xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\"
  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
  xmlns:enc=\"http://schemas.xmlsoap.org/soap/encoding/\"
  xmlns:ns1=\"http://schemas.nothing.com\"
>
<env:Body>
  <ns1:dotest>
    <book xsi:type=\"ns1:book\">
      <a xsi:type=\"xsd:string\">foo</a>
      <b xsi:type=\"xsd:string\">bar</b>
    </book>
  </ns1:dotest>
</env:Body>
<env:Header/>
</env:Envelope>";

The Code

// data object class
class book{
    public $a="a";
    public $b="c";
}

// XML transform callback function (for converting the "type" into an object)
function book_from_xml($xml) {
    $sxe = simplexml_load_string($xml);
    $obj = new book;
    $obj->a = (string)$sxe->a;
    $obj->b = (string)$sxe->b;
    return $obj;
}

// SOAP action class (called by soap handle() method)
class test
{
    function dotest($book)
    {
        $classname=get_class($book);
        return "Object: ".$classname. "(".$book->a.",".$book->b.")";
    }
}

// SOAPServer Instantiation
$options=Array(
    'actor' =>'http://schemas.nothing.com',
    'typemap' => array(
        array(
            // type namespaces have to match those declared in the WSDL
            'type_ns' => 'http://schemas.nothing.com',
            'type_name' => 'book',
            'from_xml' => 'book_from_xml',
        ),
        // additional typemap definition arrays go here
    )
);
$server = new SoapServer(dirname(__FILE__)."/classmap.wsdl",$options);
$server->setClass("test");
$server->handle($HTTP_RAW_POST_DATA);

Source Reference File

Helpful but Important Notes

  1. Input typemaps must have a from_xml callback defined, or you'll receive a segmentation fault.
  2. Output typemaps must have a to_xml callback defined, or you'll receive a segmentation fault.
  3. The type_ns namespace value must match the literal namespace defined in your WSDL or a type match won't occur.
  4. Callbacks can be more complex than the simple function callback used in the example above. Class/object methods are supported. See below.

Complex Callbacks

When using object or class methods for callbacks, you'll need to make sure to use the FQCN of your class (if you're using namespaces) and either a) declare your callback method as public static if you don't want to instantiate an instance or b) create an instance of the object first and use its method as the callback.

Here are some examples of more complex callbacks in a typemap array:

Static Class Method Call
...
array(
    // type namespaces have to match those declared in the WSDL
    'type_ns' => 'http://schemas.nothing.com',
    'type_name' => 'book',
    // myStaticCallbackMethod must be a public static function of MyClass
    'from_xml' => array('\My\Name\Space\MyClass', 'myStaticCallbackMethod'),
),

Or for PHP versions PHP 5.2.3 and above:

array(
    // type namespaces have to match those declared in the WSDL
    'type_ns' => 'http://schemas.nothing.com',
    'type_name' => 'book',
    // myStaticCallbackMethod must be a public static function of MyClass
    'from_xml' => array('\My\Name\Space\MyClass::myStaticCallbackMethod'),
),

The class definition:

namespace My\Name\Space;

class MyClass
{
    public static function myStaticCallbackMethod($xml)
    {
        // do something
    }
}
Object method call
$obj = new \My\Name\Space\MyClass();
...
// static class method call
array(
    // type namespaces have to match those declared in the WSDL
    'type_ns' => "http://schemas.nothing.com",
    'type_name' => 'book',
    'from_xml' => array($obj, 'myCallbackMethod'),
),

The class definition:

namespace My\Name\Space;

class MyClass
{
    public function myCallbackMethod($xml)
    {
        // do something
    }
}
Closures
$myCallback = function($xml) {
    // do something
};
...
// static class method call
array(
    // type namespaces have to match those declared in the WSDL
    'type_ns' => 'http://schemas.nothing.com',
    'type_name' => 'book',
    'from_xml' => $myCallback,
),
like image 184
Leo Bedrosian Avatar answered Sep 27 '22 03:09

Leo Bedrosian