Использование опции класса PHP SoapClient с WSDL, содержащим элемент и complexType с тем же именем - PullRequest
11 голосов
/ 24 сентября 2010

Я обнаружил несколько разных файлов WSDL, которые содержат элемент и complexType с одинаковым именем.Например, http://soap.search.msn.com/webservices.asmx?wsdl имеет две сущности с именем «SearchResponse»:

В этом сценарии я не могу понять, как правильно сопоставить эти сущности с классами PHP с помощью SoapClient () «classmaps»вариант.

В руководстве по PHP сказано следующее:

Параметр classmap можно использовать для сопоставления некоторых типов WSDL с классами PHP.Эта опция должна быть массивом с типами WSDL в качестве ключей и именами классов PHP в качестве значений.

К сожалению, поскольку есть два типа WSDL с одним и тем же ключом ('SearchResponse'), я не могувыяснить, как провести различие между двумя сущностями SearchResponse и назначить их соответствующим классам PHP.

Например, вот соответствующий фрагмент примера 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>

А вотPHP, который, очевидно, не будет работать , поскольку ключи classmaps одинаковы:

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

При поиске решения я обнаружил, что веб-службы Java обрабатывают это, позволяя вам указать пользовательскийсуффикс к сущностям «Element» или «ComplexType».

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

Итак, сейчас я чувствую, что просто нет способа сделать это с помощью PHP SoapClient, но яЛюбопытно, если кто-нибудь может предложить какой-либо совет.FWIW, я не могу редактировать удаленный WDSL.

Любые идеи ???

1 Ответ

7 голосов
/ 08 октября 2010

Это не в моей голове, но я думаю, вы можете сделать так, чтобы оба типа SearchResponse сопоставлялись с MY_SearchResponse, и попытаться абстрагировать разницу между ними. Это глупо, но что-то вроде этого может быть?

<?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')));
...