Using PHP SoapClient classmap option with WSDL containing an element and complexType with the same name

16,591

This is off the top of my head, but I think you could have both SearchResponse types map to MY_SearchResponse and try and abstract the difference between the two. It's kludgy, but something like this maybe?

<?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')));
Share:
16,591
Misery
Author by

Misery

As Co-Founder and CTO at Quikly, I oversee the technical development and growth of a digital marketing platform which builds urgency around branded products and promotions. Prior to Quikly, I was Technology Director and Lead Application Developer at Stereo Interactive &amp; Design, building highly-interactive database-driven websites. I also moonlight as a part-time CTO at NewMusicalTheatre.com, where we legally distribute electronic sheet music for new musical theatre writers. I majored in Economics and Political Science at the University of Michigan and have been building internet applications since 1994. Areas of expertise: web applications, scalability, performance/load testing, Ruby, Rails, Javascript, Go, React, symfony, PostgreSQL, MySQL, Redis, HTML, CSS.

Updated on June 06, 2022

Comments

  • Misery
    Misery almost 2 years

    I've encountered a few different WSDL files that contain an element and a complexType with the same name. For example, http://soap.search.msn.com/webservices.asmx?wsdl has two entities named "SearchResponse":

    In this scenario, I can't figure out how to properly map those entities to PHP classes using the SoapClient() "classmaps" option.

    The PHP manual says this:

    The classmap option can be used to map some WSDL types to PHP classes. This option must be an array with WSDL types as keys and names of PHP classes as values.

    Unfortunately, since there are two WSDL types with the same key ('SearchResponse'), I can't figure out how to differentiate between the two SearchResponse entities and assign them to their corresponding PHP classes.

    For example, here is the relevant snippet of the example 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>
    

    And here is the PHP that obviously would not work since the classmaps keys are the same:

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

    In searching for a solution, I found Java Web Services handles this by allowing you to specify a custom suffix to the "Element" or "ComplexType" entities.

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

    So, right now I feel like there is just no way to do it with PHP's SoapClient, but I'm curious if anyone out there can offer any advice. FWIW, I cannot edit the remote WDSL.

    Any ideas???