Full-service Internet Marketing & Web Development
Recent Posts

Sponsors
![]() |
PHP4 Pear/SOAP document-style bug fixomri schwartz, 02-15-2009 |
Working on integrating with Microsoft AdCenter API, I encountered a problem with the body section of the soap message.
Took a while to figure this one, so I figured I will share my findings.
Microsoft AdCenter offers a Pear/SOAP API. Pear/SOAP has two modes: 'RPC' or 'Document'.
The IBM site has a great article about the difference between RPC and Document-style web services.
In this case Microsoft AdCenter is using the 'Document' style. Integration with PHP5 built-in SOAP support, went through without any issues. But I had to get this working with PHP4.
Seems like PHP4 SOAP doesn't support the 'Document' style.
The body section of wsdl of this web service is as following:
<s:Body>
<GetCampaignsByAccountIdRequest
xmlns="https://adcenter.microsoft.com/api/advertiser/v5">
<AccountId>XXXXX</AccountId>
</GetCampaignsByAccountIdRequest>
</s:Body>
The PHP parameter for this request should be:
$param =
Array('GetCampaignsByAccountIdRequest'=>array('AccountId'=>XXXXX));
When trying to send this parameter, I kept receiving an error from SOAP_Client object, saying :
The named parameter AccountId is not in the call parameters.
Reviewing SOAP_client code:
function _generate($method, $params, $namespace = false,
$soapAction = false)
if (isset($params[$name]) ||
$this->_wsdl->getDataHandler($name, $part['namespace']))
{
$nparams[$name] =& $params[$name];
}
else
{
// We now force an associative array for
// parameters if using WSDL.
return $this->_raiseSoapFault("The named parameter $name is
not in the call parameters.");
}
Notice the SOAP_Client method is looking for the parameters in the first dimension of the parameters array.
So I tried the following parameter:
$param = array('AccountId'=>XXXXX);
No error, but the request ends up looking like this:
<s:Body>
<GetCampaignsByAccountId
xmlns="https://adcenter.microsoft.com/api/advertiser/v5">
<AccountId>XXXXX</AccountId>
</GetCampaignsByAccountId>
</s:Body>
And Microsoft AdCenter server returns:
OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'GetCampaignsByAccountIdRequest' Found node type 'Element' with name 'GetCampaignsByAccountId'.
The Problem
SOAP_Client wraps the parameter with the action name ('rpc' style).
According to pear.php.net, setting the style to 'document' should fix this.
Unfortunately, it doesn't work.
Solution
The most simple thing in this case is to set the body section as XML string parameter, but SOAP_Client class doesn't have this option. Here's how I fixed it:
Wrote a new class that inherits from SOAP_Client, overriding 2 methods:
class SOAP_Client_ex extends SOAP_Client
function _generate($method, $params, $namespace = false,
$soapAction = false)
function makeEnvelope($method, $headers, $encoding =
SOAP_DEFAULT_ENCODING, $options = array())
I've copied these functions as is from the base classes.
In override function SOAP_Client_ex->_generate, I made sure it doesn't try to serialize the parameters by changing this:
//$this->_options['input'] = 'parse';
$this->_options['input'] = 'dontparse';
In override function SOAP_Client_ex->makeEnvelope, there was already a section for not serializing:
if (!isset($options['input']) || $options['input'] == 'parse')
// some code
else
{
// $smsg = $method
$smsg = $method['bodytext']; // use xml message as is
}
Had to change it a little because $method is an array, so I specified
$smsg = $method['bodytext'].
Last step is changing the call parameters to xml:
// set parameters as xml
$paramText ='
<GetCampaignsByAccountIdRequest
xmlns="https://adcenter.microsoft.com/api/advertiser/v5">
<AccountId>'.$accountId.'</AccountId>
</GetCampaignsByAccountIdRequest>';
$result = $client->call(
'GetCampaignsByAccountId',
array('bodytext'=>$paramText),
array('trace'=>true));
And voila! All is well.
Is this a bug in PHP4 Pear/SOAP implementation?
Please reply to this post and let me know your thoughts.
Took a while to figure this one, so I figured I will share my findings.
Microsoft AdCenter offers a Pear/SOAP API. Pear/SOAP has two modes: 'RPC' or 'Document'.
The IBM site has a great article about the difference between RPC and Document-style web services.
In this case Microsoft AdCenter is using the 'Document' style. Integration with PHP5 built-in SOAP support, went through without any issues. But I had to get this working with PHP4.
Seems like PHP4 SOAP doesn't support the 'Document' style.
The body section of wsdl of this web service is as following:
<s:Body>
<GetCampaignsByAccountIdRequest
xmlns="https://adcenter.microsoft.com/api/advertiser/v5">
<AccountId>XXXXX</AccountId>
</GetCampaignsByAccountIdRequest>
</s:Body>
The PHP parameter for this request should be:
$param =
Array('GetCampaignsByAccountIdRequest'=>array('AccountId'=>XXXXX));
When trying to send this parameter, I kept receiving an error from SOAP_Client object, saying :
The named parameter AccountId is not in the call parameters.
Reviewing SOAP_client code:
function _generate($method, $params, $namespace = false,
$soapAction = false)
if (isset($params[$name]) ||
$this->_wsdl->getDataHandler($name, $part['namespace']))
{
$nparams[$name] =& $params[$name];
}
else
{
// We now force an associative array for
// parameters if using WSDL.
return $this->_raiseSoapFault("The named parameter $name is
not in the call parameters.");
}
Notice the SOAP_Client method is looking for the parameters in the first dimension of the parameters array.
So I tried the following parameter:
$param = array('AccountId'=>XXXXX);
No error, but the request ends up looking like this:
<s:Body>
<GetCampaignsByAccountId
xmlns="https://adcenter.microsoft.com/api/advertiser/v5">
<AccountId>XXXXX</AccountId>
</GetCampaignsByAccountId>
</s:Body>
And Microsoft AdCenter server returns:
OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'GetCampaignsByAccountIdRequest' Found node type 'Element' with name 'GetCampaignsByAccountId'.
The Problem
SOAP_Client wraps the parameter with the action name ('rpc' style).
According to pear.php.net, setting the style to 'document' should fix this.
Unfortunately, it doesn't work.
Solution
The most simple thing in this case is to set the body section as XML string parameter, but SOAP_Client class doesn't have this option. Here's how I fixed it:
Wrote a new class that inherits from SOAP_Client, overriding 2 methods:
class SOAP_Client_ex extends SOAP_Client
function _generate($method, $params, $namespace = false,
$soapAction = false)
function makeEnvelope($method, $headers, $encoding =
SOAP_DEFAULT_ENCODING, $options = array())
I've copied these functions as is from the base classes.
In override function SOAP_Client_ex->_generate, I made sure it doesn't try to serialize the parameters by changing this:
//$this->_options['input'] = 'parse';
$this->_options['input'] = 'dontparse';
In override function SOAP_Client_ex->makeEnvelope, there was already a section for not serializing:
if (!isset($options['input']) || $options['input'] == 'parse')
// some code
else
{
// $smsg = $method
$smsg = $method['bodytext']; // use xml message as is
}
Had to change it a little because $method is an array, so I specified
$smsg = $method['bodytext'].
Last step is changing the call parameters to xml:
// set parameters as xml
$paramText ='
<GetCampaignsByAccountIdRequest
xmlns="https://adcenter.microsoft.com/api/advertiser/v5">
<AccountId>'.$accountId.'</AccountId>
</GetCampaignsByAccountIdRequest>';
$result = $client->call(
'GetCampaignsByAccountId',
array('bodytext'=>$paramText),
array('trace'=>true));
And voila! All is well.
Is this a bug in PHP4 Pear/SOAP implementation?
Please reply to this post and let me know your thoughts.
![]() |
SeanJA, 02-26-2009 |
Have you tried PHP 5?
![]() |
Dawn Rossi, 02-26-2009 |
Hi Sean,
Yes - works without any issues with PHP5.
But we had to get it working with PHP4. This is a fix for PHP4 Pear/SOAP lack of support for the 'document' style.
Yes - works without any issues with PHP5.
But we had to get it working with PHP4. This is a fix for PHP4 Pear/SOAP lack of support for the 'document' style.
|
|
Subscribe Now to receive new posts via Email as soon as they come out.
Comments
Post your comments



