简体   繁体   中英

PHP Soap Client does not send all object properties in a webservice call

I try to implement a webservice Client using php and got stuck... I'm using an existing webservice called metadataservice with a known wsdl. I'll use wsdl2phpgenerator to create the php classes for the datatypes and the Service itself. Using one of the Webservice Methods (addMetadataToObject), I have to send an Array of objects to the Server. There is a base class:

class AssetInfo
{
    public $dataFieldId = null;
    public $dataFieldName = null;
    public $dataFieldTagName = null;
    public function __construct($dataFieldId, $dataFieldName, $dataFieldTagName)
    {
      $this->dataFieldId = $dataFieldId;
      $this->dataFieldName = $dataFieldName;
      $this->dataFieldTagName = $dataFieldTagName;
    }
}

and a derived class Holding string values (there are also other derived classes for Longs etc.):

class StringAssetInfo extends AssetInfo
{
    public $value = null;
    public function __construct($dataFieldId, $dataFieldName,$dataFieldTagName, $value)
    {
      parent::__construct($dataFieldId, $dataFieldName, $dataFieldTagName);
      $this->value = $value;
    }
}

For the call of Metadataservice->addMetadataToObject there is also a addMetadataToObject defined:

class addMetadataToObject
{
    public $objectId = null;
    public $objectType = null;
    public $assetInfos = null;
    public function __construct($objectId, $objectType)
    {
      $this->objectId = $objectId;
      $this->objectType = $objectType;
    }
} 

The property $assetInfos should hold an Array of AssetInfo objects. wdsl2phpgenerator creates a class for my MetadataService which is derived from SoapClient. This class provides all the avialable Methods for this Service. Here I only show the addMetadataToObject Method:

public function addMetadataToObject(addMetadataToObject $parameters)
{
  return $this->__soapCall('addMetadataToObject', array($parameters));
}

My Code does:

// Define the Data    
$ServiceOptions = [];
    $AssetInfos = [];
    $AssetInfo = new StringAssetInfo(2, "TitleName", "TitleName","New Title Name);        
    array_push($AssetInfos, $AssetInfo);

// Create the Service
    $Service = new MetadataService($ServiceOptions, getServiceWSDL($Options, "MetadataService"));
    $Service->__setSoapHeaders(getGalaxySoapHeader($Options));
    $NewMetaData = new addMetadataToObject(61755, "ASSET");
    $NewMetaData->assetInfos = $AssetInfos;

// Call the Service
    $failedAssets = $Service->addMetadataToObject($NewMetaData);

The call throws a Soap Exception that a value could not be extracted. Which makes me wonder. I started to monitor the traffic to the Soap Server using wireshark and yes....there is no value anymore as defined in the StringAsset Info Class...Here is the Soap Body shown by wireshark:

<SOAP-ENV:Body>
    <ns1:addMetadataToObject>
        <objectId>61755</objectId>
        <objectType>ASSET</objectType>
        <assetInfos>
            <dataFieldId>2</dataFieldId>
            <dataFieldName>TitleName</dataFieldName>
            <dataFieldTagName>TitleName</dataFieldTagName>
        </assetInfos>
    </ns1:addMetadataToObject>
Id</SOAP-ENV:Body>

I would expect a tag New Title Name. But ist gone. When I checked the $NewMetaData object in my Code or the $Parameter object in $Service->addMetadataToObject I can see that the property "Value" is defined and set. For me it seems, that the call to

return $this->__soapCall('addMetadataToObject', array($parameters));

only accepts the properties of the base class AssetInfo but not the properties from the derived class StringAssetInfo. I also changed the Code to use an Array (instead of an object) for $AssetInfo:

$AssetInfo =  array("dataFieldId"=>2, "dataFieldName"=>"TitleName","dataFieldTagName"=>"TitleName, "value"=>"New Title Name"); 

But without any change. It seems that we have here some Kind of runtime type conversion or type alignment but I can't see the reason of this. I'm still new to webservices at all and also on php (however I have to use both for the Moment:-)

Can anybody comment or give me a hint what's happening here?

I was able to realize it by using Arrays and soapvars, Please note my comments in the code:

$ServiceOptions = [];
    $AssetInfos = [];

// I have to use an Array because the Server depends on the order of the properties. I wasn't able to define expected order using the existing objects but with arrays
    $AssetInfo =  array("dataFieldId"=>2, "dataFieldName"=>"TitleName","dataFieldTagName"=>"TitleName, "value"=>"New Title Name");        

// instead of pushing the Array directly, I create an instance of an SoapVar, pass the Array as data and set the Encoding, the expected type and the Namespace uri
array_push($AssetInfos, new SoapVar($AssetInfo, SOAP_ENC_OBJECT, "StringAssetInfo", "http://metadataservice.services.provider.com"));
    array_push($AssetInfos, $AssetInfo);

// Create the Service
    $Service = new MetadataService($ServiceOptions, getServiceWSDL($Options, "MetadataService"));
    $Service->__setSoapHeaders(getGalaxySoapHeader($Options));
    $NewMetaData = new addMetadataToObject(61755, "ASSET");
    $NewMetaData->assetInfos = $AssetInfos;

// Call the Service
    $failedAssets = $Service->addMetadataToObject($NewMetaData);

This produced the expected Output in the Soap Body (and also added some namespaces to the Soap envelope

<SOAP-ENV:Body>
    <ns1:addMetadataToObject>
        <objectId>61755</objectId>
        <objectType>ASSET</objectType>
        <assetInfos xsi:type="ns1:StringAssetInfo">
            <dataFieldId>2</dataFieldId>
            <dataFieldName>TitleName</dataFieldName>
            <dataFieldTagName>TitleName</dataFieldTagName>
            <value>New Titel Name 1146</value>
        </assetInfos>
    </ns1:addMetadataToObject>
</SOAP-ENV:Body>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM