我正在准备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方法中,我有一个数组类型的参数,其中每个元素都是"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在简历中,问题是:我如何才能知道用作参数的新Custom Type的WSDL?
谢谢
发布于 2013-08-31 12:24:33
我做了类似的事情,这是一个示例代码:
/* 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 */这是类\ViewModel\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>请注意,只需更改策略和正确的DOCBLOCKS注释,就可以实现这一点。
希望这段代码能帮助你找到一个解决方案。
发布于 2018-03-28 00:46:15
以防有人从谷歌来这里,想知道问题出在哪里。
我发现这是因为docblock解析器不够智能,不能提取以非限定方式使用的类。举个例子:
<?php
use myNameSpace\MyClass;
class Foo
{
/**
* @var MyClass
*/
public $customer;
}不起作用。当Zend解析它时,它不会解析名称空间,而只是类名"MyClass",然后就会失败。
你必须这样做:
<?php
class Foo
{
/**
* The backspace qualifier is only necessary if this is namespaced.
* @var \myNameSpace\MyClass
*/
public $customer;
}https://stackoverflow.com/questions/17307571
复制相似问题