2013-06-25 20 views
6

sto preparando il server SOAP e la generazione di mia WSDL utilizzando il codice seguente:Zend Framework 2 SOAP AutoDiscover e complessi tipi

//(... 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 ...) 

Ma in uno dei miei metodo WebService ho un parametro di tipo array in cui ogni elemento è di tipo "MyOtherClass", come segue:

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

Quando provo a generare il WSDL ottengo l'errore seguente:

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 

O questo Eccezione:

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

Quando ho aggiunto al mio codice qualcosa di simile:

//(...) 
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 { 
//(...) 

ricevo il messaggio di errore seguente:

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 

Nella ripresa, la domanda è : come posso rendere noto il WSDL del nuovo Custom Type utilizzato come parametro?

Grazie

+0

'MyOtherClass []' mi sembra sbagliato nel contesto di php. Vorrei provare a creare un oggetto MyOtherClassCollection che contiene gli elementi. – DanielKhan

+0

'MyOtherClass []' definisce una matrice di oggetti MyOtherClass. Questo è assolutamente valido in PHP per le modalità Zend \ Soap \ AutoDiscover 'ArrayOfTypeSequence' e' ArrayOfTypeComplex'. –

risposta

3

ho fatto qualcosa di simile e questo è un esempio di codice:

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

Questo è un frammento della firma funzione una delle classi che l'individuazione automatica genererà il WSDL in base alla annotazioni:

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

Questa è la classe \ ViewModels \ PatientViewModel e \ ViewModel \ DiagnosisViewModel Nota come ho usato le annotazioni di dichiarare che un campo conatins una matrice di una complexType, e quindi come tale è tradotto come ArrayOfDiagnosisViewModel sulla wsdl

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; 

} 

E questo è il WSDL generato

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

AVVISO CHE, SOLO CAMBIANDO LA STRATEGIA EI GIUSTI DOCUMENTI ANNOTAZIONI, PUOI RAGGIUNGERE QUESTO.

SPERANZA QUESTI SNIPPET POSSONO AIUTARVI A TROVARE UNA SOLUZIONE.

+0

Ciao !, grazie controllerò e ti faccio sapere. +1 per le idee. – leticia

+0

tutto quello che ottengo è: Impossibile aggiungere un tipo complesso \ ViewModels \ DiagnosisViewModel ** che non è un oggetto o in cui non è stato possibile trovare la classe nella strategia "DefaultComplexType". cosa mi manca? grazie in anticipo! – wolxXx