PHP SOAP Call

For this soap xml, I have a class that works below.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getMoreBeer xmlns="http://www.uri.com/someapi">
	    <strParam1>string</strParam1>
    </getMoreBeer>
  </soap:Body>
</soap:Envelope>

Open in new window


class Beer
{
    public $strUserId = "username";
    public $strPassword = "pass";
    public $params = array();
    
 public function getMoreBeer($strParam1 = "some_brand")
    {
    
        $this->params["strParam1"]=$strParam1;

        $result = self::send('getMoreBeer');

        if(isset($result->getMoreBeer->clsStuff)){
            return $result->getMoreBeer->clsStuff;
        }else{
            return ;
        }
    }
    
  public function logindetails()
    {
        $this->params["strUserId"]=$this->strUserId;
        $this->params["strPassword"]=$this->strPassword;
    }
  public function send($action)
    {
        $this->logindetails();
        $client = new SoapClient('https://www.uri.com/someapi?wsdl');

        return $client->{$action}( $this->params );
    }
}

Open in new window


The question is what will the function look like that needs to be added to the class to target  multi level soap xml  as sample below.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getBeerBrands xmlns="http://www.uri.com/someapi">
      <objQueryStuff>
        <strParam1>string</strParam1>
        <strParam2>string</strParam2>
        <intParam3>int</intParam3>
        <objStores>
          <strParam4>string</strParam4>
        </objStores>
      </objQueryStuff>
    </getBeerBrands>
  </soap:Body>
</soap:Envelope>

Open in new window

LVL 55
Scott Fell, EE MVEDeveloper & EE ModeratorAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ray PaseurCommented:
I'll see if I can give you a PHP example in a moment, but just a suggestion -- if at all possible, get rid of SOAP and move to a RESTful interface.  The internet is littered with the rotting husks of failed SOAP project.  In contrast, I've never seen anyone who could not immediately understand and use a RESTful API.
0
Scott Fell, EE MVEDeveloper & EE ModeratorAuthor Commented:
I would, but I am consuming a 3rd party API and have no control.
0
Ray PaseurCommented:
See if this might make sense.  Dealing with SOAP namespaces is not exactly PHP's strong suit.  I find it's easier to just mung the data so you can use a path of less resistance.  Please post back if you have questions about what's going on here.
http://iconoun.com/demo/temp_padas.php
<?php // demo/temp_padas.php

/**
 * See http://www.experts-exchange.com/Programming/Languages/Scripting/PHP/Q_28645118.html
 */
error_reporting(E_ALL);
echo '<pre>';

$xml = <<<EOD
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getBeerBrands xmlns="http://www.uri.com/someapi">
      <objQueryStuff>
        <strParam1>string</strParam1>
        <strParam2>string</strParam2>
        <intParam3>int</intParam3>
        <objStores>
          <strParam4>string</strParam4>
        </objStores>
      </objQueryStuff>
    </getBeerBrands>
  </soap:Body>
</soap:Envelope>
EOD;


// LOAD THE XML STRING
$obj = simplexml_load_string(mungXML($xml));

// ACTIVATE THIS TO SHOW THE ENTIRE OBJECT MADE FROM THE MUNG XML
// var_dump($obj);

// USE AN ITERATOR TO FIND DATA INSIDE THE OBJECT
foreach ($obj->soap_Body as $b)
{
    var_dump($b);
}

// USE DIRECT ADDRESSING TO FIND DATA INSIDE THE OBJECT
$d = $obj->soap_Body->getBeerBrands->objQueryStuff->objStores;
var_dump($d);



// FUNCTION TO MUNG THE XML SO WE DO NOT HAVE TO DEAL WITH NAMESPACE
function mungXML($xml)
{
    $obj = SimpleXML_Load_String($xml);
    if ($obj === FALSE) return $xml;

    // GET NAMESPACES, IF ANY
    $nss = $obj->getNamespaces(TRUE);
    if (empty($nss)) return $xml;

    // CHANGE ns: INTO ns_
    $nsm = array_keys($nss);
    foreach ($nsm as $key)
    {
        // A REGULAR EXPRESSION TO MUNG THE XML
        $rgx
        = '#'               // REGEX DELIMITER
        . '('               // GROUP PATTERN 1
        . '\<'              // LOCATE A LEFT WICKET
        . '/?'              // MAYBE FOLLOWED BY A SLASH
        . preg_quote($key)  // THE NAMESPACE
        . ')'               // END GROUP PATTERN
        . '('               // GROUP PATTERN 2
        . ':{1}'            // A COLON (EXACTLY ONE)
        . ')'               // END GROUP PATTERN
        . '#'               // REGEX DELIMITER
        ;
        // INSERT THE UNDERSCORE INTO THE TAG NAME
        $rep
        = '$1'          // BACKREFERENCE TO GROUP 1
        . '_'           // LITERAL UNDERSCORE IN PLACE OF GROUP 2
        ;
        // PERFORM THE REPLACEMENT
        $xml =  preg_replace($rgx, $rep, $xml);
    }
    return $xml;
}

Open in new window

0
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

Scott Fell, EE MVEDeveloper & EE ModeratorAuthor Commented:
It was all going nicely until there was nesting.

Would it be easier to use cURL?  Convert the xml to a $variable and submit via cURL.  That's what I used to do for Classic ASP where everything was done by hand.

<?php
  $soap_request  = "<?xml version=\"1.0\"?>\n";
  $soap_request .= "<soap:Envelope xmlns:soap=\"http://www.w3.org/2001/12/soap-envelope\" soap:encodingStyle=\"http://www.w3.org/2001/12/soap-encoding\">\n";
  $soap_request .= "  <soap:Body xmlns:m=\"http://www.example.org/stock\">\n";
  $soap_request .= "    <m:GetStockPrice>\n";
  $soap_request .= "      <m:StockName>IBM</m:StockName>\n";
  $soap_request .= "    </m:GetStockPrice>\n";
  $soap_request .= "  </soap:Body>\n";
  $soap_request .= "</soap:Envelope>";
 
  $header = array(
    "Content-type: text/xml;charset=\"utf-8\"",
    "Accept: text/xml",
    "Cache-Control: no-cache",
    "Pragma: no-cache",
    "SOAPAction: \"run\"",
    "Content-length: ".strlen($soap_request),
  );
 
  $soap_do = curl_init();
  curl_setopt($soap_do, CURLOPT_URL, "http://localhost/php-soap-curl/soap-server.php" );
  curl_setopt($soap_do, CURLOPT_CONNECTTIMEOUT, 10);
  curl_setopt($soap_do, CURLOPT_TIMEOUT,        10);
  curl_setopt($soap_do, CURLOPT_RETURNTRANSFER, true );
  curl_setopt($soap_do, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($soap_do, CURLOPT_SSL_VERIFYHOST, false);
  curl_setopt($soap_do, CURLOPT_POST,           true );
  curl_setopt($soap_do, CURLOPT_POSTFIELDS,     $soap_request);
  curl_setopt($soap_do, CURLOPT_HTTPHEADER,     $header);
 
  if(curl_exec($soap_do) === false) {
    $err = 'Curl error: ' . curl_error($soap_do);
    curl_close($soap_do);
    print $err;
  } else {
    curl_close($soap_do);
    print 'Operation completed without any errors';
  }

Open in new window

http://eureka.ykyuen.info/2011/05/05/php-send-a-soap-request-by-curl/
0
Ray PaseurCommented:
Maybe I'm missing something. I thought you wanted to consume the SOAP output.

Is there API documentation available?
0
Ray PaseurCommented:
See if this makes sense.  It uses the sample SOAP 1.2 data from the API.
http://iconoun.com/demo/temp_padas.php
<?php // demo/temp_padas.php

/**
 * See http://www.experts-exchange.com/Programming/Languages/Scripting/PHP/Q_28645118.html
 */
error_reporting(E_ALL);
echo '<pre>';

// FUNCTION TO MUNG THE XML SO WE DO NOT HAVE TO DEAL WITH NAMESPACE
function mungXML($xml)
{
    $obj = SimpleXML_Load_String($xml);
    if ($obj === FALSE) return $xml;

    // GET NAMESPACES, IF ANY
    $nss = $obj->getNamespaces(TRUE);
    if (empty($nss)) return $xml;

    // CHANGE ns: INTO ns_
    $nsm = array_keys($nss);
    foreach ($nsm as $key)
    {
        // A REGULAR EXPRESSION TO MUNG THE XML
        $rgx
        = '#'               // REGEX DELIMITER
        . '('               // GROUP PATTERN 1
        . '\<'              // LOCATE A LEFT WICKET
        . '/?'              // MAYBE FOLLOWED BY A SLASH
        . preg_quote($key)  // THE NAMESPACE
        . ')'               // END GROUP PATTERN
        . '('               // GROUP PATTERN 2
        . ':{1}'            // A COLON (EXACTLY ONE)
        . ')'               // END GROUP PATTERN
        . '#'               // REGEX DELIMITER
        ;
        // INSERT THE UNDERSCORE INTO THE TAG NAME
        $rep
        = '$1'          // BACKREFERENCE TO GROUP 1
        . '_'           // LITERAL UNDERSCORE IN PLACE OF GROUP 2
        ;
        // PERFORM THE REPLACEMENT
        $xml =  preg_replace($rgx, $rep, $xml);
    }
    return $xml;
}


$xml = <<<EOD
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <getReservationQueryResponse xmlns="http://www.DELIBREATELY_OBSCURED_API">
      <getReservationQueryResult>
        <dblTotalGoods>double</dblTotalGoods>
        <dblTotalTax>double</dblTotalTax>
        <dblTotalCost>double</dblTotalCost>
        <blnHasCSA>boolean</blnHasCSA>
        <dblCSAAmount>double</dblCSAAmount>
        <dblDues>double</dblDues>
        <arrCharges>
          <clsCharge>
            <strDesc>string</strDesc>
            <dblAmount>double</dblAmount>
            <dblTax>double</dblTax>
            <enumType>SecurityDeposit or Rent or Other</enumType>
          </clsCharge>
          <clsCharge>
            <strDesc>string</strDesc>
            <dblAmount>double</dblAmount>
            <dblTax>double</dblTax>
            <enumType>SecurityDeposit or Rent or Other</enumType>
          </clsCharge>
        </arrCharges>
        <arrPayments>
          <clsPayment>
            <dtDuedate>dateTime</dtDuedate>
            <dblAmount>double</dblAmount>
          </clsPayment>
          <clsPayment>
            <dtDuedate>dateTime</dtDuedate>
            <dblAmount>double</dblAmount>
          </clsPayment>
        </arrPayments>
        <dblSecurityDeposit>double</dblSecurityDeposit>
        <objInsuranceDetails>
          <objTravelInsurance>
            <dblAmount>double</dblAmount>
            <strPolicyNumber>string</strPolicyNumber>
          </objTravelInsurance>
          <objDamageInsurance>
            <dblAmount>double</dblAmount>
            <strPolicyNumber>string</strPolicyNumber>
          </objDamageInsurance>
        </objInsuranceDetails>
      </getReservationQueryResult>
    </getReservationQueryResponse>
  </soap12:Body>
</soap12:Envelope>
EOD;


// LOAD THE XML STRING
$obj = simplexml_load_string(mungXML($xml));

// ACTIVATE THIS TO SHOW THE ENTIRE OBJECT MADE FROM THE MUNG XML
// var_dump($obj);

// THIS APPEARS TO BE JUST WRAPPER TAGS
$data = $obj->soap12_Body->getReservationQueryResponse->getReservationQueryResult;

// FIND SOME DATA ELEMENTS IN THE OBJECTS AND ARRAYS
$x = $data->dblTotalCost;
echo PHP_EOL . "dblTotalCost: $x";

$x = $data->blnHasCSA;
echo PHP_EOL . "blnHasCSA: $x";

foreach ($data->arrCharges->clsCharge as $x)
{
    echo PHP_EOL . "x->strDesc: $x->strDesc";
    echo PHP_EOL . "x->enumType: $x->enumType";
}

foreach ($data->arrPayments->clsPayment as $x)
{
    echo PHP_EOL . "x->dtDuedate: $x->dtDuedate";
    echo PHP_EOL . "x->dblAmount: $x->dblAmount";
}

$x = $data->objInsuranceDetails;
print_r($x);

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Scott Fell, EE MVEDeveloper & EE ModeratorAuthor Commented:
Thanks Ray, I will give it a try
0
Scott Fell, EE MVEDeveloper & EE ModeratorAuthor Commented:
Sorry for the delay in accepting.  Ray is always a great resource.
0
Ray PaseurCommented:
Thanks for the points, Scott!  All the best, ~Ray
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.