2010-09-24 15 views
10

J'ai rencontré quelques fichiers WSDL différents contenant un élément et un complexType du même nom. Par exemple, http://soap.search.msn.com/webservices.asmx?wsdl a deux entités nommées "SearchResponse":Utilisation de l'option de classeur PHP SoapClient avec WSDL contenant un élément et complexType du même nom

Dans ce scénario, je ne peux pas comprendre comment mapper correctement ces entités aux classes PHP à l'aide de l'option "classmaps" SoapClient().

Le manuel PHP dit ceci:

L'option classmap peut être utilisée pour cartographier certains types WSDL aux classes PHP. Cette option doit être un tableau avec les types WSDL en tant que clés et les noms des classes PHP en tant que valeurs.

Malheureusement, car il existe deux types WSDL avec la même clé (« SearchResponse »), je ne peux pas savoir comment faire la différence entre les deux entités SearchResponse et les affecter à leurs classes PHP correspondantes.

Par exemple, voici l'extrait pertinent du WSDL exemple:

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

Et voici le PHP qui évidemment fonctionne pas puisque les classmaps clés sont les mêmes:

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

Dans la recherche d'une solution, j'ai trouvé que Java Web Services gère cela en vous permettant de spécifier un suffixe personnalisé aux entités "Element" ou "ComplexType".

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

Alors, en ce moment je me sens comme il n'y a aucun moyen de le faire avec SoapClient de PHP, mais je suis curieux de savoir si quelqu'un là-bas peut offrir des conseils. FWIW, je ne peux pas éditer le WDSL à distance.

Des idées ???

+0

Aucune idée immédiate, mais vous pouvez vérifier le commentaire à http://www.php.net/manual/en/soapclient.soapclient.php#94151. En utilisant le 'SoapClient -> __ getTypes()' mentionné, vous pourriez trouver une différenciation de type 'implicite' des deux éléments que vous pouvez utiliser (juste une supposition, cependant). –

+0

Henrik, merci pour votre commentaire. __getTypes() retourne des détails intéressants sur les structures de données disponibles et dans mon cas, j'obtiens deux 'structures' avec le même nom qui ont des attributs différents. Hélas, le problème demeure: je ne peux pas mapper ces deux structs à différentes classes PHP en raison de la façon dont le paramètre classmap est mis en place (où la clé de tableau est le nom de la structure). – stereoscott

Répondre

7

Cela me vient à l'esprit, mais je pense que vous pourriez faire correspondre les deux types de SearchResponse à MY_SearchResponse et essayer de faire abstraction de la différence entre les deux. C'est kludgy, mais quelque chose comme ça peut-être?

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

C'est assez intéressant. J'ai joué avec ça et ça marche plutôt bien. Je devais juste dépasser le fait que je devais utiliser la même classe pour les deux types d'entités. – stereoscott

+0

Aussi ... Je pense que l'envoi de demandes de savon au serveur en utilisant la classe ne fonctionnerait pas, mais je pourrais imaginer créer une méthode qui produirait les paramètres appropriés pour dépendre de quel élément de savon il représente et l'envoyer. Merci pour votre exemple détaillé. – stereoscott

+0

Oui, c'est une stratégie de nommage assez ambiguë de la part des fournisseurs WS.Je suis content que je puisse être utile. –