将PHP SoapClient类映射选项与包含同名元素和complexType的WSDL一起使用

将PHP SoapClient类映射选项与包含同名元素和complexType的WSDL一起使用,php,soap,wsdl,soap-client,Php,Soap,Wsdl,Soap Client,我遇到了几个不同的WSDL文件,其中包含一个元素和一个同名的complexType。例如,有两个名为“SearchResponse”的实体: 在这个场景中,我不知道如何使用SoapClient()“classmaps”选项正确地将这些实体映射到PHP类 PHP手册中说: classmap选项可用于映射 将一些WSDL类型转换为PHP类。这 选项必须是具有WSDL的数组 类型作为PHP类的键和名称 作为价值观 不幸的是,由于有两种WSDL类型具有相同的键(“SearchResponse”),因此我

我遇到了几个不同的WSDL文件,其中包含一个元素和一个同名的complexType。例如,有两个名为“SearchResponse”的实体:

在这个场景中,我不知道如何使用SoapClient()“classmaps”选项正确地将这些实体映射到PHP类

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,因为类映射键是相同的:

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

在搜索解决方案时,我发现JavaWeb服务通过允许您为“Element”或“ComplexType”实体指定自定义后缀来处理此问题

所以,现在我觉得用PHP的SoapClient无法做到这一点,但我很好奇是否有人能提供任何建议。FWIW,我无法编辑远程WDSL


有什么想法吗?

这是我想不出来的,但我认为您可以将两种SearchResponse类型映射到我的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')));

目前还不清楚,但您可以在查看评论。使用前面提到的
SoapClient->\uuu getTypes()
,您可能会发现可以使用的两个元素的“隐式”类型差异(不过只是一个猜测)。Henrik,感谢您的评论__getTypes()返回有关可用数据结构的一些有趣细节,在我的例子中,我得到了两个具有不同属性的同名“struct”。唉,问题仍然存在:由于classmap参数的设置方式(其中数组键是结构的名称),我无法将这两个结构映射到不同的PHP类。这非常有趣。我一直在玩这个,它的工作相当好。我必须克服这样一个事实,我必须对两种类型的实体使用相同的类。而且。。。我认为使用类like向服务器发送Soap请求是不可行的,但我可以想象创建一个方法,该方法将根据它所表示的Soap元素输出适当的参数,然后发送该参数。感谢您的详细示例。是的,WS-providers的命名策略相当模糊。我很高兴我能帮上忙。