How to make a PHP SOAP call using the SoapClient class

Viewed 464482

I'm used to writing PHP code, but do not often use Object-Oriented coding. I now need to interact with SOAP (as a client) and am not able to get the syntax right. I've got a WSDL file which allows me to properly set up a new connection using the SoapClient class. However, I'm unable to actually make the right call and get data returned. I need to send the following (simplified) data:

  • Contact ID
  • Contact Name
  • General Description
  • Amount

There are two functions defined in the WSDL document, but I only need one ("FirstFunction" below). Here is the script I run to get information on the available functions and types:

$client = new SoapClient("http://example.com/webservices?wsdl");
var_dump($client->__getFunctions()); 
var_dump($client->__getTypes()); 

And here is the output it generates:

array(
  [0] => "FirstFunction Function1(FirstFunction $parameters)",
  [1] => "SecondFunction Function2(SecondFunction $parameters)",
);

array(
  [0] => struct Contact {
    id id;
    name name;
  }
  [1] => string "string description"
  [2] => string "int amount"
}

Say I want to make a call to the FirstFunction with the data:

  • Contact ID: 100
  • Contact Name: John
  • General Description: Barrel of Oil
  • Amount: 500

What would be the right syntax? I've been trying all sorts of options but it appears the soap structure is quite flexible so there are very many ways of doing this. Couldn't figure it out from the manual either...


UPDATE 1: tried sample from MMK:

$client = new SoapClient("http://example.com/webservices?wsdl");

$params = array(
  "id" => 100,
  "name" => "John",
  "description" => "Barrel of Oil",
  "amount" => 500,
);
$response = $client->__soapCall("Function1", array($params));

But I get this response: Object has no 'Contact' property. As you can see in the output of getTypes(), there is a struct called Contact, so I guess I somehow need to make clear my parameters include the Contact data, but the question is: how?

UPDATE 2: I've also tried these structures, same error.

$params = array(
  array(
    "id" => 100,
    "name" => "John",
  ),
  "Barrel of Oil",
  500,
);

As well as:

$params = array(
  "Contact" => array(
    "id" => 100,
    "name" => "John",
  ),
  "description" => "Barrel of Oil",
  "amount" => 500,
);

Error in both cases: Object has no 'Contact' property`

13 Answers

First, use SoapUI to create your soap project from the wsdl. Try to send a request to play with the wsdl's operations. Observe how the xml request composes your data fields.

And then, if you are having problem getting SoapClient acts as you want, here is how I debug it. Set the option trace so that the function __getLastRequest() is available for use.

$soapClient = new SoapClient('http://yourwdsdlurl.com?wsdl', ['trace' => true]);
$params = ['user' => 'Hey', 'account' => '12345'];
$response = $soapClient->__soapCall('<operation>', $params);
$xml = $soapClient->__getLastRequest();

Then the $xml variable contains the xml that SoapClient compose for your request. Compare this xml with the one generated in the SoapUI.

For me, SoapClient seems to ignore the keys of the associative array $params and interpret it as indexed array, causing wrong parameter data in the xml. That is, if I reorder the data in $params, the $response is completely different:

$params = ['account' => '12345', 'user' => 'Hey'];
$response = $soapClient->__soapCall('<operation>', $params);

I had the same issue, but I just wrapped the arguments like this and it works now.

    $args = array();
    $args['Header'] = array(
        'CustomerCode' => 'dsadsad',
        'Language' => 'fdsfasdf'
    );
    $args['RequestObject'] = $whatever;

    // this was the catch, double array with "Request"
    $response = $this->client->__soapCall($name, array(array( 'Request' => $args )));

Using this function:

 print_r($this->client->__getLastRequest());

You can see the Request XML whether it's changing or not depending on your arguments.

Use [ trace = 1, exceptions = 0 ] in SoapClient options.

getLastRequest():

This method works only if the SoapClient object was created with the trace option set to TRUE.

TRUE in this case is represented by 1

$wsdl = storage_path('app/mywsdl.wsdl');
try{

  $options = array(
               // 'soap_version'=>SOAP_1_1,
               'trace'=>1,
               'exceptions'=>1,
               
                'cache_wsdl'=>WSDL_CACHE_NONE,
             //   'stream_context' => stream_context_create($arrContextOptions)
        );
           // $client = new \SoapClient($wsdl, array('cache_wsdl' => WSDL_CACHE_NONE) );
        $client = new \SoapClient($wsdl, array('cache_wsdl' => WSDL_CACHE_NONE));
        $client     = new \SoapClient($wsdl,$options);

There is an option to generate php5 objects with WsdlInterpreter class. See more here: https://github.com/gkwelding/WSDLInterpreter

for example:

require_once 'WSDLInterpreter-v1.0.0/WSDLInterpreter.php';
$wsdlLocation = '<your wsdl url>?wsdl';
$wsdlInterpreter = new WSDLInterpreter($wsdlLocation);
$wsdlInterpreter->savePHP('.');

Below code might be helpful

    $wsdl ='My_WSDL_Service.wsdl";
    $options = array(
        'login' => 'user-name',
        'password' => 'Password',
    );
    try {
        $client = new SoapClient($wsdl, $options);
        $params = array(
            'para1' => $para1,
            'para2' => $para2
        );
        $res = $client->My_WSDL_Service($params);
Related