php - Zend Framework 2 SOAP 自动发现和复杂类型

标签 php wsdl zend-framework2 soapserver zend-soap

我正在准备 SOAP 服务器并使用以下代码生成我的 WSDL:

//(... Controller action code ...)
if (key_exists('wsdl', $params)) {
    $autodiscover = new AutoDiscover();
    $autodiscover->setClass('WebServiceClass')
                 ->setUri('http://server/webserver/uri');
    $autodiscover->handle();
} else {
    $server = new Server(null);
    $server->setUri($ws_url);
    $server->setObject($this->getServiceLocator()->get('MyController\Service\WebServiceClass'));
    $server->handle();
}

//(... Controller action code ...)

但是在我的一个 WebService 方法中,我有一个 Array 类型的参数,其中每个元素都是“MyOtherClass”类型,如下所示:

    /**
     * Add list of MyOtherClass items
     *
     * @param MyOtherClass[]    $items
     *
     * @return bool
     */
    function add($items) {
        // Function code here
    }

当我尝试生成 WSDL 时,出现以下错误:

PHP Warning:  DOMDocument::loadXML(): Empty string supplied as input in /<zend framweork path>/Server/vendor/zendframework/zendframework/library/Zend/Soap/Server.php on line 734

或者这个异常:

Cannot add a complex type MyOtherClass[] that is not an object or where class could not be found in "DefaultComplexType" strategy.

当我在我的代码中添加如下内容时:

//(...)
if (key_exists('wsdl', $params)) {

    $autodiscover = new AutoDiscover();
    $autodiscover->setClass('WebServiceClass');
    $autodiscover->setUri($ws_url);

    $complex_type_strategy = new \Zend\Soap\Wsdl\ComplexTypeStrategy\ArrayOfTypeComplex();
    $complex_type_strategy->addComplexType('MyOtherClass');
    $autodiscover->setComplexTypeStrategy($complex_type_strategy);
    $autodiscover->handle();
} else {
//(...)

我收到以下错误消息:

Fatal error: Call to a member function getTypes() on a non-object in /<project dir>/vendor/zendframework/zendframework/library/Zend/Soap/Wsdl/ComplexTypeStrategy/AbstractComplexTypeStrategy.php on line 54

在简历中,问题是:我怎样才能知道用作参数的新自定义类型的 WSDL?

谢谢

最佳答案

我做了类似的事情,这是一个示例代码:

/* code.... */
if (array_key_exists('wsdl', $this->request->getQuery()) || array_key_exists('WSDL', $this->request->getQuery())) {

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

                    $auto->setClass($controllerClassName);
                    $auto->setUri(sprintf('%s://%s%s', \Application\Bootstrap::getServiceManager()->get('config')[APPLICATION_ENV]['webServer']['protocol'],
                                                     $this->request->getUri()->getHost() , $this->request->getUri()->getPath()));
                    $auto->setServiceName(ucfirst($this->request->getModuleName()) . ucfirst($this->request->getControllerName()));

                    header('Content-type: application/xml');

                    echo $auto->toXML();



                } elseif (count($this->request->getQuery()) == 0) {

                    $this->preDispatch();

                    $wsdl = sprintf('%s://%s%s?wsdl', \Application\Bootstrap::getServiceManager()->get('config')[APPLICATION_ENV]['webServer']['protocol'],
                                                     $this->request->getUri()->getHost() , $this->request->getUri()->getPath());

                    $soapServer = new \Zend\Soap\Server($wsdl);
                    $soapServer->setClass($controllerClassName);
                    $soapServer->handle();
                }

/* code */

这是自动发现将根据注释生成 wsdl 的类之一的函数签名片段:

/**
 * Allows to search for a patient based on the patient id
 *
 * @param int $id
 * @return \ViewModels\PatientViewModel
 * @throws \Application\Exception
 */
protected function searchPatientById($id) {
 /* .... code */

这是类\ViewModels\PatientViewModel 和\ViewModel\DiagnosisViewModel 注意这里我是如何使用注释来声明一个字段包含一个复杂类型的数组,然后是如何在 wsdl 上将其转换为 ArrayOfDiagnosisViewModel

    namespace ViewModels;

    class PatientViewModel {

        /**
         * @var int
         * */
        public $id;

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

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

        /**
         *** @var \ViewModels\DiagnosisViewModel[]**
         * */
        public $diagnosis;

    }

class DiagnosisViewModel {

    /**
     * @var int
     */
    public $id;

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

}

这是生成的 WSDL

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://soa.local/soap/Sample/Main" 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="SampleMain" targetNamespace="http://soa.local/soap/Sample/Main">
    <types>
        <xsd:schema targetNamespace="http://soa.local/soap/Sample/Main">
            <xsd:complexType name="DiagnosisViewModel">
                <xsd:all>
                    <xsd:element name="id" type="xsd:int" nillable="true"/>
                    <xsd:element name="name" type="xsd:string" nillable="true"/>
                </xsd:all>
            </xsd:complexType>
            **<xsd:complexType name="ArrayOfDiagnosisViewModel">
                <xsd:sequence>
                    <xsd:element name="item" type="tns:DiagnosisViewModel" minOccurs="0" maxOccurs="unbounded"/>
                </xsd:sequence>
            </xsd:complexType>**
            <xsd:complexType name="PatientViewModel">
                <xsd:all>
                    <xsd:element name="id" type="xsd:int" nillable="true"/>
                    <xsd:element name="firstname" type="xsd:string" nillable="true"/>
                    <xsd:element name="lastname" type="xsd:string" nillable="true"/>
                    <xsd:element name="diagnosis" type="tns:ArrayOfDiagnosisViewModel" nillable="true"/>
                </xsd:all>
            </xsd:complexType>
        </xsd:schema>
    </types>
    <portType name="SampleMainPort">
        <operation name="searchPatientById">
            <documentation>Allows to search for a patient based on the patient id</documentation>
            <input message="tns:searchPatientByIdIn"/>
            <output message="tns:searchPatientByIdOut"/>
        </operation>
    </portType>
    <binding name="SampleMainBinding" type="tns:SampleMainPort">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="searchPatientById">
            <soap:operation soapAction="http://soa.local/soap/Sample/Main#searchPatientById"/>
            <input>
                <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://soa.local/soap/Sample/Main"/>
            </input>
            <output>
                <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://soa.local/soap/Sample/Main"/>
            </output>
        </operation>
    </binding>
    <service name="SampleMainService">
        <port name="SampleMainPort" binding="tns:SampleMainBinding">
            <soap:address location="http://soa.local/soap/Sample/Main"/>
        </port>
    </service>
    <message name="searchPatientByIdIn">
        <part name="id" type="xsd:int"/>
    </message>
    <message name="searchPatientByIdOut">
        <part name="return" type="tns:PatientViewModel"/>
    </message>
</definitions>

请注意,只需更改策略和正确的文档 block 注释,您就可以实现这一目标。

希望这些片段可以帮助您找到解决方案。

关于php - Zend Framework 2 SOAP 自动发现和复杂类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17307571/

相关文章:

javascript - PHP 服务器上的 HTML 数据挖掘

php - MVC - URI 中没有 Controller ?

java - 从 wsdl 生成 java 类

web-services - Radixx API 示例

authentication - 使用 Zend Framework 2 通过 HTTP 身份验证阻止访问

php - 选择是否将文件保存在数据库中作为 blob ajax php

PHP 将 MySQL 行检索到数组中

grails - 基于WSDL的Groovy/Grails模拟Web服务

php - Zend Framework 1 与 Zend Framework 2 性能对比

php - ZF2 Redis : how to set expiration time for a key