ZF2 and implementing a SOAP server returning a complex type
Asked Answered
C

1

0

I'm trying to implement a SOAP server using Zend Framework 2 in PHP5.5. I've come as far as this:

library.php

<?php
namespace Library;

class IncrementedInt
{
    /**
     * @var integer
     **/
    public $original;

    /**
     * @var integer
     **/
    public $incremented;

    public function __construct($num)
    {
        $this->original = $num;
        $this->incremented = ++$num;
    }
}

webservice.php

<?php
require_once 'library.php';
require_once 'Zend/Loader/StandardAutoloader.php';

$loader = new Zend\Loader\StandardAutoloader(array('autoregister_zf' => true));
$loader->register();

class Math
{
    /**
     * This method takes ...
     *
     * @param integer $inputParam
     * @return \Library\IncrementedInt
     */
    public function increment($inputParam)
    {
        return new \Library\IncrementedInt($inputParam);
    }
}

if (isset($_GET['wsdl'])) {
    $autodiscover = new \Zend\Soap\AutoDiscover();
    $autodiscover->setClass('Math')
                 ->setBindingStyle(array('style' => 'document'))
                 ->setUri('http://localhost' . $_SERVER['SCRIPT_NAME']);
    header('Content-type: application/xml');
    echo $autodiscover->toXml();
}
else {
    // pointing to the current file here
    $soap = new \Zend\Soap\Server('http://localhost' . $_SERVER['SCRIPT_NAME'] . '?wsdl');
    $soap->setClass('Math');
    $soap->handle();
}

Loading the URL http://localhost/webservice.php?wsdl in a browser will output:

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://localhost/webservice.php" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" name="Math" targetNamespace="http://localhost/webservice.php">
    <script/>
    <types>
        <xsd:schema targetNamespace="http://localhost/webservice.php">
            <xsd:element name="increment">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="inputParam" type="xsd:int"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
            <xsd:complexType name="IncrementedInt">
                <xsd:all>
                    <xsd:element name="original" type="xsd:int" nillable="true"/>
                    <xsd:element name="incremented" type="xsd:int" nillable="true"/>
                </xsd:all>
            </xsd:complexType>
            <xsd:element name="incrementResponse">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="incrementResult" type="tns:IncrementedInt"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
        </xsd:schema>
    </types>
    <portType name="MathPort">
        <operation name="increment">
            <documentation>This method takes ...</documentation>
            <input message="tns:incrementIn"/>
            <output message="tns:incrementOut"/>
        </operation>
    </portType>
    <binding name="MathBinding" type="tns:MathPort">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="increment">
            <soap:operation soapAction="http://localhost/webservice.php#increment"/>
            <input>
                <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
            </input>
            <output>
                <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
            </output>
        </operation>
    </binding>
    <service name="MathService">
        <port name="MathPort" binding="tns:MathBinding">
            <soap:address location="http://localhost/webservice.php"/>
        </port>
    </service>
    <message name="incrementIn">
        <part name="parameters" element="tns:increment"/>
    </message>
    <message name="incrementOut">
        <part name="parameters" element="tns:incrementResponse"/>
    </message>
</definitions>

As you can see the IncrementedInt class and its properties original and incremented are defined. Yet when I call the service with sending this XML (using soapUI):

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://localhost/webservice.php">
   <soapenv:Header/>
   <soapenv:Body>
      <web:increment>
         <inputParam xsi:type="xsd:int">2</inputParam>
      </web:increment>
   </soapenv:Body>
</soapenv:Envelope>

The server will respond like:

<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://localhost/webservice.php" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Body>
      <ns1:incrementResponse>
         <return xsi:type="ns1:IncrementedInt"/>
      </ns1:incrementResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

As you can see the return value is not expanded and it's just like the type is named. Has anyone successfully returned a complex type in ZF2 SOAP server? How? I searched the Internet for an example but I could not find any!

Caliginous answered 18/9, 2013 at 9:22 Comment(4)
I am a litle confused how are you running zendframework 2 on a php 5.2? The min. requirement is 5.3.3 or 5.4 if you intend to use traits.framework.zend.com/issues/browse/ZF2-537Titian
OK you've got me, it's PHP5.5. I just meant that PHP has got the namespaces, that's all. I'll update the question, thanks for correcting me.Caliginous
Why are you not using the buildin zf2 soap server/client? framework.zend.com/manual/2.0/en/modules/zend.soap.server.html framework.zend.com/manual/2.0/en/modules/zend.soap.client.htmlTitian
Perhaps there's been a misunderstanding, because that's what I'm using!Caliginous
C
1

It turned out all I was missing was the fact that Zend Framework caches WSDLs by default. So all I needed to do was to:

<?php
require_once 'library.php';
require_once 'Zend/Loader/StandardAutoloader.php';

$loader = new Zend\Loader\StandardAutoloader(array('autoregister_zf' => true));
$loader->register();

class Math
{
    /**
     * This method takes ...
     *
     * @param integer $inputParam
     * @return \Library\IncrementedInt
     */
    public function increment($inputParam)
    {
        return new \Library\IncrementedInt($inputParam);
    }
}

if (isset($_GET['wsdl'])) {
    $autodiscover = new \Zend\Soap\AutoDiscover();
    $autodiscover->setClass('Math')
                 ->setUri('http://localhost' . $_SERVER['SCRIPT_NAME']);
    header('Content-type: application/xml');
    echo $autodiscover->toXml();
}
else {
    // pointing to the current file here
    $soap = new \Zend\Soap\Server('http://localhost' . $_SERVER['SCRIPT_NAME'] . '?wsdl', array('cache_wsdl' => WSDL_CACHE_NONE));
    $soap->setClass('Math');
    $soap->handle();
}

The changes are:

  1. When instantiating a Server it is set as options to disable WSDL caching.
  2. The ->setBindingStyle(array('style' => 'document')) method call to AutoDiscovery is omitted as it causes trouble and prevents a successful SOAP call.
Caliginous answered 18/9, 2013 at 12:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.