Search code examples
phpsoapsoap-client

PHP SoapClient: How to prefix SOAP parameter tag name with namespace?


I'm using PHP's SoapClient to consume a SOAP service but am receiving an error that the SOAP service cannot see my parameters.

<tns:GenericSearchResponse xmlns:tns="http://.../1.0">
  <tns:Status>
    <tns:StatusCode>1</tns:StatusCode>
    <tns:StatusMessage>Invalid calling system</tns:StatusMessage>
  </tns:Status>
</tns:GenericSearchResponse>

The XML PHP's SoapClient sends for the SOAP call:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:ns1="http://.../1.0">
  <SOAP-ENV:Body>
    <ns1:GenericSearchRequest>
      <UniqueIdentifier>12345678</UniqueIdentifier>
      <CallingSystem>WEB</CallingSystem>
    </ns1:GenericSearchRequest>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

I used soap-ui initially, that works successfully when consuming the same WSDL. The XML soap-ui sends for the call:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:ns1="http://.../1.0">
  <SOAP-ENV:Body>
    <ns1:GenericSearchRequest>
      <ns1:UniqueIdentifier>12345678</ns1:UniqueIdentifier>
      <ns1:CallingSystem>WEB</ns1:CallingSystem>
    </ns1:GenericSearchRequest>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The difference being the UniqueIdentifier and CallingSystem parameters are prefixed with ns1 in the soap-ui request.

I've tried using passing SoapVar objects to the SoapClient call but this does not augment the parameter tags and prefix them with ns1.

I know that WEB is a valid CallingSystem value as the XSD specifies it, and it works when using soap-ui.

My current SoapClient code:

try {
  $client = new SoapClient($wsdl, array('trace' => 1));
  $query = new stdClass;
  $query->UniqueIdentifier = $id;
  $query->CallingSystem = 'WEB';
  $response = $client->GenericUniqueIdentifierSearch($query);
} catch (SoapFault $ex) {
  $this->view->error = $ex->getMessage();
  ...
}

I found this blog post but I was hoping there might be a cleaner implementation.

Update: Used a solution from this question but is pretty clunky:

$xml = "<ns1:GenericSearchRequest>"
     . "<ns1:UniqueIdentifier>$id</ns1:UniqueIdentifier>"
     . "<ns1:CallingSystem>WEB</ns1:CallingSystem>"
     . "</ns1:GenericSearchRequest>";
$query = new SoapVar($xml, XSD_ANYXML);

$response = $this->client->__SoapCall(
    'GenericUniqueIdentifierSearch',
    array($query)
);

Solution

  • Use a SoapVar to namespace the GenericSearchRequest fields:

    $xml = "<ns1:GenericSearchRequest>"
         . "<ns1:UniqueIdentifier>$id</ns1:UniqueIdentifier>"
         . "<ns1:CallingSystem>WEB</ns1:CallingSystem>"
         . "</ns1:GenericSearchRequest>";
    $query = new SoapVar($xml, XSD_ANYXML);
    
    $response = $this->client->__SoapCall(
        'GenericUniqueIdentifierSearch',
        array($query)
    );