Search code examples
phpsoapzend-framework2soap-client

SOAP client with Zend framework 2


I'm trying to create a SOAP client in Zend framework 2, I've created the below which returns the data correctly

try {
  $client = new Zend\Soap\Client("http://www.webservicex.net/country.asmx?WSDL");
  $result = $client->GetCountries();      
  print_r($result);
} catch (SoapFault $s) {
  die('ERROR: [' . $s->faultcode . '] ' . $s->faultstring);
} catch (Exception $e) {
  die('ERROR: ' . $e->getMessage());
}

however when I try to send data to the webservice for example using

try {
  $client = new Zend\Soap\Client("http://www.webservicex.net/country.asmx?WSDL");
  $result = $client->GetCurrencyByCountry('Australia');
  print_r($result);
} catch (SoapFault $s) {
  die('ERROR: [' . $s->faultcode . '] ' . $s->faultstring);
} catch (Exception $e) {
  die('ERROR: ' . $e->getMessage());
}

I just get the following message

ERROR: [soap:Receiver] System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.Data.SqlClient.SqlException: Procedure or function 'GetCurrencyByCountry' expects parameter '@name', which was not supplied. at WebServicex.country.GetCurrencyByCountry(String CountryName) --- End of inner exception stack trace ---

How do I supply parameters to the webservices ?


Solution

  • Your problem is in the request, the WDSL defines complex types:

    <s:element name="GetCurrencyByCountryResponse">
        <s:complexType>
            <s:sequence>
                <s:element minOccurs="0" maxOccurs="1" name="GetCurrencyByCountryResult" type="s:string"/>
            </s:sequence>
        </s:complexType>
    </s:element>
    

    So what you need is to built an object or an assoziative array in order to be consumed by the webservice. For the object variant you can use a stdClass. If you to modify the function call like this:

    $params = new \stdClass(); 
    $params->CountryName = 'Australia'; 
    $result = $client->GetCurrencyByCountry($params); 
    

    Your request fits the type and the data will be send to the server. In the provided WDSL there are even more complex variants you have to handle:

    <wsdl:message name="GetISOCountryCodeByCountyNameSoapOut"> 
        <wsdl:part name="parameters" element="tns:GetISOCountryCodeByCountyNameResponse"/> 
    </wsdl:message>
    

    Would need a setup like this:

    $params = new \stdClass();
    $params->parameters = new \stdClass();
    $params->parameters->GetISOCountryCodeByCountyNameResult = 'YOURVALUE';
    

    Or as an array:

    $params = array('parameters'=> 
      array('GetISOCountryCodeByCountyNameResult'=>'VALUE')
    );