ZF2并实现返回复杂类型的SOAP服务器

时间:2013-09-18 09:22:26

标签: zend-framework2 complextype soapserver

我正在尝试使用PHP5.5中的Zend Framework 2实现SOAP服务器。我已经达到了这个目的:

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();
}

在浏览器中加载网址http://localhost/webservice.php?wsdl将输出:

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

正如您所看到的,IncrementedInt类及其属性originalincremented已定义。然而,当我通过发送此XML(使用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>

服务器将响应如下:

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

正如您所看到的,返回值未展开,就像类型被命名一样。有没有人成功返回ZF2 SOAP服务器中的复杂类型?怎么样?我在互联网上搜索了一个例子,但我找不到任何一个!

1 个答案:

答案 0 :(得分:1)

事实证明,我所缺少的是Zend Framework默认缓存WSDL的事实。所以我需要做的就是:

<?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();
}

变化是:

  1. 实例化Server时,它被设置为禁用WSDL缓存的选项。
  2. 省略对->setBindingStyle(array('style' => 'document'))的{​​{1}}方法调用,因为它会导致麻烦并阻止成功的SOAP调用。