Get soap response in php

Get received XML from PHP SOAP Server

I’m using the build-in SOAP-Server within a symfony2 application and beside handling the StdClass-Object, I would need to read the complete xml received for debugging and logging. Is there a way to simply catch the transferred xml? It should be somewhere in the request header, but I simply can’t find it there.

quoting: soap_request — The SOAP request. If this argument is omitted, the request is assumed to be in the raw POST data of the HTTP request.

Ok, so you suggest I read the xml direkt from the raw http post? What is strange is, that the soap server is working but I cannot get any POST or GET data; Both seems to be empty. Do you have any idea where the xml request can be stored? I tried all variables but I’m not able to catch any relevant data.

2 Answers 2

I was looking for the same thing and finally found it. Hope this helps you or someone else.

$postdata = file_get_contents("php://input"); 

The $postdata variable will have the raw XML. Found through the following two links:

The raw XML transmitted in a SOAP envelope should be in the POST body. In a Symfony application, you can get the body of the POST request by creating a Request object and calling its getContents() method.

Within a Controller

You can get request contents easily in the controller, like so:

// src/MyProject/MyBundle/Controller/MyController.php use Symfony\Component\HttpFoundation\Request; . $request = Request::createFromGlobals(); $soapEnvelope = $request->getContents(); 

Within a Service

Best practice (for Symfony 2.4+) is to inject a RequestStack into your service class within the service container. You can do it as a constructor argument to your service class, by invoking a setter method, etc. Here’s a quick example using injection via the constructor.

Читайте также:  Collections and arraylist java

In your service container:

// src/MyProject/MyBundle/Resources/config/services.xml   

Then in your service class:

// src/MyProject/MyBundle/Service/MyService.php use Symfony\Component\HttpFoundation\RequestStack; . class MyServiceClass < /** * @var RequestStack $rs */ private $requestStack; /** * Constructor * * @param RequestStack $requestStack */ public function __construct(RequestStack $requestStack) < $this->requestStack = $requestStack; > /** * Some method where you need to access the raw SOAP xml */ public function myMethod() < $request = $this->requestStack->getCurrentRequest(); $soapEnvelope = $request->getContents(); > > 

Источник

SoapClient::__getLastResponse

Note:

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

Parameters

This function has no parameters.

Return Values

The last SOAP response, as an XML string.

Examples

Example #1 SoapClient::__getLastResponse() example

$client = SoapClient ( «some.wsdl» , array( ‘trace’ => 1 ));
$result = $client -> SomeFunction ();
echo «Response:\n» . $client -> __getLastResponse () . «\n» ;
?>

See Also

  • SoapClient::__getLastResponseHeaders() — Returns the SOAP headers from the last response
  • SoapClient::__getLastRequest() — Returns last SOAP request
  • SoapClient::__getLastRequestHeaders() — Returns the SOAP headers from the last request

User Contributed Notes 4 notes

D’oh!
That example needs:
$soapClient = new SoapClient($url, array(‘trace’=>1));
to turn ON tracing in the first place.

You almost for sure will need to wrap a try/catch block around your SOAP call in order to use these to debug something that’s not working.

Otherwise, PHP throws a fatal error before you can execute this function.

For example:
$soapClient = new SoapClient ( $url );
echo htmlentities ( $soapClient -> __getFunctions ());
//Assume that has output ‘someFunction’ (among others)
try $results = $soapClient -> someFunction (. );
>
catch ( SoapFault $soapFault ) var_dump ( $soapFault );
echo «Request :
» , htmlentities ( $soapClient -> __getLastRequest ()), «
» ;
echo «Response :
» , htmlentities ( $soapClient -> __getLastResponse ()), «
» ;
>
?>

Without try/catch, your just get the Fatal Error and PHP commits suicide before you can call __getLastRequest/__getLastResponse

Just to make it a bit more readable

echo «REQUEST:\n» . htmlentities(str_ireplace(‘>\n__getLastRequest())) . «\n»;
echo «RESPONSE:\n» . htmlentities(str_ireplace(‘>\n__getLastResponse())) . «\n»;

PS: If you are using \n then you need to enclose above statements in . You can also use
, but it gets a bit messy.

You don’t need to surround SoapClient in a try-catch block. Just set the «exceptions» option to false, and the SoapFault instance will be returned instead of thrown.

  • SoapClient
    • _​_​call
    • _​_​construct
    • _​_​doRequest
    • _​_​getCookies
    • _​_​getFunctions
    • _​_​getLastRequest
    • _​_​getLastRequestHeaders
    • _​_​getLastResponse
    • _​_​getLastResponseHeaders
    • _​_​getTypes
    • _​_​setCookie
    • _​_​setLocation
    • _​_​setSoapHeaders
    • _​_​soapCall

    Источник

    SOAP

    PROBLEM (with SOAP extension under PHP5) of transferring object, that contains objects or array of objects. Nested object would not transfer.

    SOLUTION:
    This class was developed by trial and error by me. So this 23 lines of code for most developers writing under PHP5 solves fate of using SOAP extension.

    /*
    According to specific of organization process of SOAP class in PHP5, we must wrap up complex objects in SoapVar class. Otherwise objects would not be encoded properly and could not be loaded on remote SOAP handler.

    Function «getAsSoap» call for encoding object for transmission. After encoding it can be properly transmitted.
    */
    abstract class SOAPable public function getAsSOAP () foreach( $this as $key =>& $value ) $this -> prepareSOAPrecursive ( $this -> $key );
    >
    return $this ;
    >

    private function prepareSOAPrecursive (& $element ) if( is_array ( $element )) foreach( $element as $key =>& $val ) $this -> prepareSOAPrecursive ( $val );
    >
    $element =new SoapVar ( $element , SOAP_ENC_ARRAY );
    >elseif( is_object ( $element )) if( $element instanceof SOAPable ) $element -> getAsSOAP ();
    >
    $element =new SoapVar ( $element , SOAP_ENC_OBJECT );
    >
    >
    >

    class PersonList extends SOAPable protected $ArrayOfPerson ; // variable MUST be protected or public!
    >

    class Person extends SOAPable //any data
    >

    $client =new SoapClient ( «test.wsdl» , array( ‘soap_version’ => SOAP_1_2 , ‘trace’ => 1 , ‘classmap’ => array( ‘Person’ => «Person» , ‘PersonList’ => «PersonList» ) ));

    $PersonList =new PersonList ;

    $client -> someMethod ( $PersonList );

    ?>

    So every class, which will transfer via SOAP, must be extends from class SOAPable.
    As you can see, in code above, function prepareSOAPrecursive search another nested objects in parent object or in arrays, and if does it, tries call function getAsSOAP() for preparation of nested objects, after that simply wrap up via SoapVar class.

    So in code before transmitting simply call $obj->getAsSOAP()

    If you are having an issue where SOAP cannot find the functions that are actually there if you view the wsdl file, it’s because PHP is caching the wsdl file (for a day at a time). To turn this off, have this line on every script that uses SOAP: ini_set(«soap.wsdl_cache_enabled», «0»); to disable the caching feature.

    Juste a note to avoid wasting time on php-soap protocol and format support.

    Until php 5.2.9 (at least) the soap extension is only capable of understanding wsdl 1.0 and 1.1 format.

    The wsdl 2.0, a W3C recommendation since june 2007, ISN’T supported in php soap extension.
    (the soap/php_sdl.c source code don’t handle wsdl2.0 format)

    The wsdl 2.0 is juste the 1.2 version renamed because it has substantial differences from WSDL 1.1.

    The differences between the two format may not be invisible if you don’t care a lot.

    The typical error message if you provide a wsdl 2.0 format file :
    PHP Fatal error: SOAP-ERROR: Parsing WSDL: Couldn’t find in ‘wsdl/example.wsdl’ in /path/client.php on line 9

    Was calling an asmx method like $success=$x->AuthenticateUser($userName,$password) and this was returning me an error.

    However i changed it and added the userName and password in an array and its now KAWA.

    If anyone is trying to use this for accessing Sabre’s web services, it won’t work. Sabre checks the request header «Content-Type» to see if it is «text/xml» . If it is not text/xml then it sends an error back.

    You will need to create a socket connection and use that to send the request over.

    Here is an example of a php client talking to a asmx server:

    // Prepare SoapHeader parameters
    $sh_param = array(
    ‘Username’ => ‘username’ ,
    ‘Password’ => ‘password’ );
    $headers = new SoapHeader ( ‘http://soapserver.example.com/webservices’ , ‘UserCredentials’ , $sh_param );

    // Prepare Soap Client
    $soapClient -> __setSoapHeaders (array( $headers ));

    // Setup the RemoteFunction parameters
    $ap_param = array(
    ‘amount’ => $irow [ ‘total_price’ ]);

    // Call RemoteFunction ()
    $error = 0 ;
    try <
    $info = $soapClient -> __call ( «RemoteFunction» , array( $ap_param ));
    > catch ( SoapFault $fault ) <
    $error = 1 ;
    print( »
    alert(‘Sorry, blah returned the following ERROR: » . $fault -> faultcode . «-» . $fault -> faultstring . «. We will now take you back to our home page.’);
    window.location = ‘main.php’;
    » );
    >

    if ( $error == 0 ) <
    $auth_num = $info -> RemoteFunctionResult ;

    // Setup the OtherRemoteFunction() parameters
    $at_param = array(
    ‘amount’ => $irow [ ‘total_price’ ],
    ‘description’ => $description );

    // Call OtherRemoteFunction()
    $trans = $soapClient -> __call ( «OtherRemoteFunction» , array( $at_param ));
    $trans_result = $trans -> OtherRemoteFunctionResult ;
    .
    > else <
    // Record the transaction error in the database

    // Kill the link to Soap
    unset( $soapClient );
    >
    >
    >
    >

    Источник

Оцените статью