2013-06-25 10 views
6

mam przygotowanie serwera SOAP i WSDL generowania moją pomocą kodu następująco:Zend Framework 2 SOAP autodiscover i złożone typy

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

Ale w jednym z mojej metody WebService Mam parametr typu Array, w której każdy element jest typu "MyOtherClass", jak następuje:

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

Kiedy próbuję wygenerować WSDL pojawia się błąd następująco:

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 

Albo ten wyjątek:

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

Kiedy dodałem do mojego kodu tak:

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

pojawia się komunikat o błędzie następująco:

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 

W życiorysie, pytanie : jak mogę rozpoznać WSDL nowego typu niestandardowego używanego jako parametr?

Dzięki

+0

'MyOtherClass []' wygląda mi nie tak w kontekście php. Chciałbym spróbować utworzyć obiekt MyOtherClassCollection, który przechowuje elementy. – DanielKhan

+0

'MyOtherClass []' definiuje tablicę obiektów MyOtherClass. Jest to całkowicie w porządku w PHP dla trybów Zend \ Soap \ AutoDiscover 'ArrayOfTypeSequence' oraz' ArrayOfTypeComplex'. –

Odpowiedz

3

Zrobiłem coś podobnego i to jest przykładowy kod:

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

Jest to fragment podpisu funkcji jednej z klas, że autodiscover będą generować WSDL oparte na adnotacje:

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

jest to klasa \ ViewModels \ PatientViewModel i \ ViewModel \ DiagnosisViewModel Wskazówka tutaj jak użyłem adnotacje o stwierdzenie, że pole conatins tablicę z complexType, a następnie, jak to jest tłumaczone jako ArrayOfDiagnosisViewModel na 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; 

} 

I to jest WSDL generowane

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

OGŁOSZENIE, ŻE TYLKO ZMIANA STRATEGII I PRAWDOPODOBNYCH REKOMENDACJI DOKUMENTÓW MOŻESZ OSIĄGNĄĆ.

NADZIEJĘ TEN SNIPPETS MOŻNA POMÓC W ZAKRESIE ROZWIĄZANIA.

+0

Cześć !, dzięki, że to sprawdzę i dam znać. +1 za pomysły. – leticia

+0

wszystko, co otrzymuję, to: Nie można dodać typu złożonego \ ViewModels \ DiagnosisViewModel **, który nie jest obiektem lub gdy nie można znaleźć klasy w strategii "DefaultComplexType". czego mi brakuje? Z góry! – wolxXx