PHP SoapParam/SoapVar for complex type gives "object hasn't 'xxx' property" - repeating element

BillF picture BillF · Jan 12, 2011 · Viewed 17.6k times · Source

This question relates to the use of SoapParam and SoapVar in a PHP SOAP client to handle repeating elements, where requests cannot be framed as associative arrays. More particularly, it addresses a difficulty in using SoapParam/SoapVar for complex elements.

I have working code that I am trying to modify to allow a repeated element in the SOAP request.

The working code is as follows and correctly returns details of a single consignmentID.

$oClient = new SoapClient($wsdlFilespec, $arguments);
$parameters = array(
   'header' => array(
      'source' => $_POST['source'],
      'accountNo' => $_POST['accountNo'],
      'userAccessKey' => $connection['userAccessKey']
      ),
   'consignmentId' => $_POST['consignmentId']
     );
$request = array('parameters' => $parameters);
$result = $oClient->__soapCall($operation, $request);

I now need to be able to pass in multiple consignmentIds and obviously an associative array won't work for that. So I have been trying to use SoapParam and SoapVar; not finding a lot of documentation or examples for these by the way.

I have tried the following:

$header = array(
   new SoapParam((string)$_POST['source'], 'source'), 
   new SoapParam((int)$_POST['accountNo'], 'accountNo'),
   new SoapParam((string)$connection['userAccessKey'], 'userAccessKey')
  );

$parameters = array(
   new SoapParam($header, 'header'),
   new SoapParam((string)'PDH44109', 'consignmentId'),
   new SoapParam((string)'PDH44110', 'consignmentId')
     );
$request = array('parameters' => $parameters);

This gives: SOAP-ERROR: Encoding: object hasn't 'header' property.

I have also tried using SoapVar in hopes of forcing the complex type of 'header', as follows:

$header = array(
  new SoapParam((string)$_POST['source'], 'source'), 
  new SoapParam((int)$_POST['accountNo'], 'accountNo'),
  new SoapParam((string)$connection['userAccessKey'], 'userAccessKey')
  );
$headerVar = new SoapVar($header, SOAP_ENC_OBJECT, 'TransactionHeaderType',     
"http://myexpress/Common/actions/externals/Consignment/v1");

$parameters = array(
           new SoapParam($headerVar, 'header'),
   new SoapParam((string)'PDH44109', 'consignmentId'),
   new SoapParam((string)'PDH44110', 'consignmentId')
     );
$request = array('parameters' => $parameters);

This also gives: SOAP-ERROR: Encoding: object hasn't 'header' property.

I have also tried variations on the last line of code such as:

$request = array('parameters' => $parameters);
$request = array($parameters);
$request = $parameters;

As an experiment I temporarily assigned a string to $header and then was able to peek at the XML generated by __soapCall prior to calling __doRequest and found that it contained the following:

<SOAPENV:Body><ns1:getConsignmentDetailRequest/>
<consignmentId>PDH44109</consignmentId><consignmentId>PDH44110</consignmentId>
</SOAP-ENV:Body>

You can see that the multiple consignments have been correctly included -- that part seems to be solved -- but 'header' (a complex type) is omitted completely.

Would so much appreciate any help whatever! I am a real beginner and have spent more than a day on this. Am quite uncertain with SoapVar, for example, what the appropriate parameters are.

Perhaps there is an issue with the typing of 'header'? Have provided some wsdl extracts below for reference.

------

<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://my.com.au/ESB/Services/Concrete/External/Services/v1" 

xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns0="http://myexpress/Common/actions/externals/Consignment/v1" 

xmlns:ns1="http://myexpress/Common/externals/Faultv1" xmlns:ns2="http://myexpress/Common/actions/externals/FreightCalculation/v1" 

xmlns:ns3="http://myexpress/Common/Primitives/v1" xmlns:ns4="http://myexpress/Common/FreightProcessing/v1" 

xmlns:ns5="http://myexpress/Common/Account/v1" xmlns:ns6="http://myexpress/Common/Imaging/v1" name="Untitled" 

targetNamespace="http://my.com.au/ESB/Services/Concrete/External/Services/v1">

------

        <xsd:schema xmlns="http://myexpress/Common/Primitives/v1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 

xmlns:acc="http://myexpress/Common/Account/v1" targetNamespace="http://myexpress/Common/Primitives/v1" elementFormDefault="qualified" 

attributeFormDefault="unqualified">
            <xsd:import namespace="http://myexpress/Common/Account/v1"/>
   .
   .
   .
   .

           <xsd:complexType name="TransactionHeaderType">
                <xsd:sequence>
                    <xsd:element name="source" type="xsd:string"/>
                    <xsd:element name="accountNo" type="xsd:integer"/>
                    <xsd:element name="userAccessKey" type="xsd:string"/>
                    <xsd:element name="userId" type="ns3:userIdType" minOccurs="0"/>
                    <xsd:element name="transactionId" type="ns3:transactionIdType" minOccurs="0"/>
                    <xsd:element name="transactionDatetime" type="xsd:dateTime" minOccurs="0"/>
                </xsd:sequence>
            </xsd:complexType>

------

            <xsd:simpleType name="consignmentIdType">
                <xsd:restriction base="xsd:string">
                    <xsd:maxLength value="30"/>
                </xsd:restriction>
            </xsd:simpleType>

------

            <xsd:element name="getConsignmentDetailRequest">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="header" type="prim:TransactionHeaderType"/>
                        <xsd:element name="consignmentId" type="ns0:consignmentIdType" maxOccurs="unbounded"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>

------

Answer

BillF picture BillF · Jan 17, 2011

After thrashing around with SoapVar and SoapParam for days and getting nowhere, found the following simple solution:

$oClient = new SoapClient($wsdlFilespec, $arguments); 
$parameters = array(
                    'header' => array(
                                      'source' => $_POST['source'],
                                      'accountNo' => $_POST['accountNo'],
                                      'userAccessKey' => $connection['userAccessKey']
                                     ),
                    'consignmentId' => array('PDH44109', 'PDH44110')
                    );
$request = array('parameters' => $parameters);
$result = $oClient->__soapCall($operation, $request);