2010-09-24 8 views
10

Napotkałem kilka różnych plików WSDL, które zawierają element i complexType o tej samej nazwie. Na przykład http://soap.search.msn.com/webservices.asmx?wsdl ma dwie jednostki o nazwie "SearchResponse":Używanie opcji mapowania klasy SoapClient z WSDL zawierającej element i complexType o tej samej nazwie

W tym scenariuszu nie mogę dowiedzieć się, jak poprawnie odwzorować te obiekty na klasy PHP za pomocą opcji "classmaps" SoapClient().

Podręcznik PHP mówi tak:

Opcja classmap mogą być używane do mapowania niektórych typów WSDL klas PHP. Ta opcja musi być tablicą z typami WSDL jako kluczami i nazwami klas PHP jako wartościami.

Niestety, ponieważ istnieją dwa rodzaje WSDL z tego samego klucza („SearchResponse”), nie mogę dowiedzieć się, jak rozróżniać pomiędzy tymi dwoma podmiotami SearchResponse i przypisać je do odpowiednich klas PHP.

Na przykład, tutaj jest odpowiedni fragment przykładowego WSDL:

<xsd:complexType name="SearchResponse"> 
    <xsd:sequence> 
     <xsd:element minOccurs="1" maxOccurs="1" name="Responses" type="tns:ArrayOfSourceResponseResponses"/> 
    </xsd:sequence> 
</xsd:complexType> 

<xsd:element name="SearchResponse"> 
    <xsd:complexType> 
     <xsd:sequence> 
      <xsd:element minOccurs="1" maxOccurs="1" name="Response" type="tns:SearchResponse"/> 
     </xsd:sequence> 
    </xsd:complexType> 
</xsd:element> 

I tu jest PHP, który oczywiście będzie nie działać od czasu classmaps klawiszy są takie same:

<?php $server = new SoapClient("http://soap.search.msn.com/webservices.asmx?wsdl", array('classmap' => array('SearchResponse' => 'MySearchResponseElement', 'SearchResponse' => 'MySearchResponseComplexType'))); ?> 

Szukając rozwiązania, znalazłem, że Java Web Services obsługuje to, umożliwiając określenie niestandardowego sufiksu w elementach "Element" lub "ComplexType".

http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/1.5/tutorial/doc/JAXBUsing4.html#wp149350

Więc teraz czuję się jak tam jest po prostu nie da się zrobić z PHP SoapClient, ale jestem ciekawy, czy ktoś tam może zaoferować jakąś radę. FWIW, nie mogę edytować zdalnego WDSL.

Jakieś pomysły ???

+0

Brak natychmiastowego pomysłu, ale można sprawdzić komentarz na http://www.php.net/manual/en/soapclient.soapclient.php#94151. Używając wspomnianego 'SoapClient -> __ getTypes()', możesz znaleźć "niejawne" zróżnicowanie typów dwóch elementów, których możesz użyć (tylko zgadnij). –

+0

Henrik, dziękuję za komentarz. __getTypes() zwraca kilka interesujących szczegółów na temat dostępnych struktur danych iw moim przypadku otrzymuję dwie "struktury" o tej samej nazwie, które mają różne atrybuty. Niestety, problem pozostaje: nie mogę mapować tych dwóch struktur do różnych klas PHP ze względu na sposób konfigurowania parametru classmap (gdzie klucz tablicy jest nazwą struktury). – stereoscott

Odpowiedz

7

To jest poza moim zasięgiem, ale myślę, że możesz mieć oba typy SearchResponse mapować do MY_SearchResponse i spróbować zlikwidować różnicę między tymi dwoma. To kludgy, ale może coś takiego?

<?php 
//Assuming SearchResponse<complexType> contains SearchReponse<element> which contains and Array of SourceResponses 
//You could try abstracting the nested Hierarchy like so: 
class MY_SearchResponse 
{ 
    protected $Responses; 
    protected $Response; 

    /** 
    * This should return the nested SearchReponse<element> as a MY_SearchRepsonse or NULL 
    **/ 
    public function get_search_response() 
    { 
     if($this->Response && isset($this->Response)) 
     { 
     return $this->Response; //This should also be a MY_SearchResponse 
     } 
     return NULL; 
    } 

    /** 
    * This should return an array of SourceList Responses or NULL 
    **/ 
    public function get_source_responses() 
    { 
     //If this is an instance of the top SearchResponse<complexType>, try to get the SearchResponse<element> and it's source responses 
     if($this->get_search_response() && isset($this->get_search_response()->get_source_responses())) 
     { 
     return $this->get_search_response()->get_source_responses(); 
     } 
     //We are already the nested SearchReponse<element> just go directly at the Responses 
     elseif($this->Responses && is_array($this->Responses) 
     { 
     return $this->Responses; 
     } 
     return NULL; 
    } 
} 

class MY_SourceResponse 
{ 
    //whatever properties SourceResponses have 
} 

$client = new SoapClient("http:/theurl.asmx?wsdl", array('classmap' => array('SearchResponse' => 'MY_SearchResponse', 'SourceResponse' => 'MY_SourceResponse'))); 
+0

To jest całkiem interesujące. Grałem z tym i działa całkiem dobrze. Po prostu musiałem przejść przez to, że muszę używać tej samej klasy dla obu typów jednostek. – stereoscott

+0

Również ... Myślę, że wysyłanie żądań Soap do serwera przy użyciu klasy nie działałoby, ale mógłbym sobie wyobrazić stworzenie metody, która wyprowadziłaby odpowiednie parametry zależnie od tego, który element mydła reprezentuje i wysłał go zamiast tego. Dzięki za twój szczegółowy przykład. – stereoscott

+0

Tak, to dość niejednoznaczna strategia nazewnictwa ze strony dostawców WS.Cieszę się, że mogę ci pomóc. –