文字

SOAP

  • 简介
  • 安装/配置
    • 需求
    • 安装
    • 运行时配置
    • 资源类型
  • 预定义常量
  • SOAP 函数
    • is_soap_fault — Checks if a SOAP call has failed
    • use_soap_error_handler — Set whether to use the SOAP error handler
  • SoapClient — The SoapClient class
    • SoapClient::__call — Calls a SOAP function (deprecated)
    • SoapClient::__construct — SoapClient constructor
    • SoapClient::__doRequest — Performs a SOAP request
    • SoapClient::__getFunctions — Returns list of available SOAP functions
    • SoapClient::__getLastRequest — Returns last SOAP request
    • SoapClient::__getLastRequestHeaders — Returns the SOAP headers from the last request
    • SoapClient::__getLastResponse — Returns last SOAP response
    • SoapClient::__getLastResponseHeaders — Returns the SOAP headers from the last response
    • SoapClient::__getTypes — Returns a list of SOAP types
    • SoapClient::__setCookie — The __setCookie purpose
    • SoapClient::__setLocation — Sets the location of the Web service to use
    • SoapClient::__setSoapHeaders — Sets SOAP headers for subsequent calls
    • SoapClient::__soapCall — Calls a SOAP function
    • SoapClient::SoapClient — SoapClient constructor
  • SoapServer — The SoapServer class
    • SoapServer::addFunction — 添加一个或多个函数来处理SOAP请求
    • SoapServer::addSoapHeader — Add a SOAP header to the response
    • SoapServer::__construct — SoapServer constructor
    • SoapServer::fault — Issue SoapServer fault indicating an error
    • SoapServer::getFunctions — Returns list of defined functions
    • SoapServer::handle — Handles a SOAP request
    • SoapServer::setClass — Sets the class which handles SOAP requests
    • SoapServer::setObject — Sets the object which will be used to handle SOAP requests
    • SoapServer::setPersistence — Sets SoapServer persistence mode
    • SoapServer::SoapServer — SoapServer constructor
  • SoapFault — The SoapFault class
    • SoapFault::__construct — SoapFault constructor
    • SoapFault::SoapFault — SoapFault constructor
    • SoapFault::__toString — Obtain a string representation of a SoapFault
  • SoapHeader — The SoapHeader class
    • SoapHeader::__construct — SoapHeader constructor
    • SoapHeader::SoapHeader — SoapHeader constructor
  • SoapParam — The SoapParam class
    • SoapParam::__construct — SoapParam constructor
    • SoapParam::SoapParam — SoapParam constructor
  • SoapVar — The SoapVar class
    • SoapVar::__construct — SoapVar constructor
    • SoapVar::SoapVar — SoapVar constructor

用户评论:

[#1] Luke [2015-09-08 07:21:15]

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...

[#2] spectrumcat at gmail dot com [2015-02-22 16:19:47]

In case you'll get a .p12 certificate for your SOAP client to use (or any other actually) make sure to convert it to PEM and merge with the private key. 

Convert p12 to PEM with merged private key:
openssl pkcs12 -in supplied_cert.p12 -out php_soap_cert.pem -clcerts

Example:
$wsdl = "./mywsdl.wsdl"; // Or "http://provider.com/api/api.wsdl"

$options = [
        'location'      => "http://provider.com/api/",
        'local_cert'    => "./php_soap_cert.pem",
        'passphrase'    => "certificate_password",
];

try {
    $soapClient = new SoapClient($wsdl, $options);
} catch(Exception $e) {
    var_dump($e);
}

[#3] rafinskipg at gmail dot com [2012-05-14 14:54:54]

Support for MTOM addign this code to your project:

<?php 
class MySoapClient extends SoapClient
{
    public function 
__doRequest($request$location$action$version$one_way 0)
    {
        
$response parent::__doRequest($request$location$action$version$one_way);
        
// parse $response, extract the multipart messages and so on
        
        //this part removes stuff
        
$start=strpos($response,'<?xml');
        
$end=strrpos($response,'>');    
        
$response_string=substr($response,$start,$end-$start+1);
        return(
$response_string);
    }
}

?>


Then you can do this 
<?php
  
new MySoapClient($wsdl_url);
?>

[#4] dennis at pleasedontspam dot clansman dot nl [2011-12-02 03:53:10]

When you receive the soapfault message: "looks like we got no XML document" it might be that you're talking to a server that supports MTOM (http://www.w3.org/TR/soap12-mtom/). 

MTOM is, as of yet (5.3.6), not supported by the SoapClient.

[#5] mariamr at gmail dot com [2010-10-16 18:38:27]

??SOAP-ERROR: Parsing WSDL: Couldn??t find in ??PATH/TO/YOUR/WSDL????

This error occurs because some versions of PHP SOAP client  do not send the user name and password that you pass as the options input parameter of the SoapClient constructor  . Yu need to pass the credentials in the web service URL like this:
$soapClient =new SoapClient(??http://user:password@example.com/blahblah.wsdl??);

[#6] vishal dot thakkar at exateam dot com [2010-02-22 06:19:18]

I was trying to figure out for days and days to make SOAP server return an associative array and NOT an object ....

To get an array (not object) in the SOAP response, just serialize the array before returning it to the clent..

hope it helps...
Thanks.....
Vishal Thakkar.

[#7] stephenlansell at gmail dot com [2010-02-03 19:19:55]

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

<?php

        $soapClient 
= new SoapClient("https://soapserver.example.com/blahblah.asmx?wsdl"); 
    
        
// 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;
            
            if (
$auth_num 0) {
                ....

                
// 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);
            }
        }
    }    
}
    
?>

[#8] moazzam at moazzam-khan dot com [2009-10-05 09:37:44]

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.

[#9] Raphal Gertz [2009-04-18 21:50:43]

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 wsdl 1.0 format structure (see http://www.w3.org/TR/wsdl) :
<definitions ...>
    <types ...>
    </types>
    <message ...>
        <part ...>
    </message>
    <portType ...>
        <operation ...>
            <input ... />
            <output ... />
            <fault ... />
        </operation>
    </portType>
    <binding ...>
        <operation ...>
            <input ... />
            <output ... />
            <fault ... />
        </operation>
    </binding>
    <service ...>
        <port ...>
    </service>
</definitions>

And the wsdl 2.0 format structure (see http://www.w3.org/TR/wsdl20/) :
<description ...>
    <types ...>
    </types>
    <interface ...>
        <fault ... />
        <operation ...>
            <input ... />
            <output ... />
            <fault ... />
        </operation>
    </interface>
    <binding ...>
        <fault ... />
        <operation ...>
            <input ... />
            <output ... />
            <fault ... />
        </operation>
    </binding>
    <service ...>
        <endpoint ...>
    </service>
</description>

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

[#10] jeff at jeffrodriguez dot com [2009-02-03 13:37:06]

Named parameters are actually super easy once you know how to do it. No need to bother with SoapParam or SoapVar for the most part.

The code:
<?php
$ws
->getAsset(array(
  
'assetId' => 5967
));
?>


Generates the following SOAP body: (formatted for readability)
<SOAP-ENV:Body>
  <ns1:getAsset>
    <assetId>5967</assetId>
  </ns1:getAsset>
</SOAP-ENV:Body>

[#11] beau dot scott at gmail dot com [2008-10-22 15:34:51]

If you've been trying to send null to a service that considers empty property tags as empty strings rather than null, here's an extending class that fixes this using xsi:nil:

<?php
class XSoapClient extends SoapClient
{
    const 
XSI_NS "http://www.w3.org/2001/XMLSchema-instance";
    const 
_NULL_ "xxx_replacedduetobrokephpsoapclient_xxx";

    protected 
$mustParseNulls false;

    public function 
__doRequest($request$location$action$version$one_way null)
    {
        if(
$this->mustParseNulls)
        {
            
$this->mustParseNulls false;
            
$request preg_replace('/<ns1:(\w+)>'.self::_NULL_.'<\/ns1:\\1>/',
                        
'<ns1:$1 xsi:nil="true"/>',
                        
$request, -1, &$count);

            if (
$count 0)
            {
                
$request preg_replace('/(<SOAP-ENV:Envelope )/',
                    
'\\1 xmlns:xsi="'.self::XSI_NS.'" ',
                    
$request);
            }
        }
        return 
parent::__doRequest($request$location$action$version$one_way);
    }

    public function 
__call($method$params)
    {
        foreach(
$params as $k => $v)
        {
            if(
$v === null)
            {
                
$this->mustParseNulls true;
                
$params[$k] = self::_NULL_;
            }
        }
        return 
parent::__call($method$params);
    }
}
?>

[#12] Ryan [2008-10-22 06:21:59]

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.

[#13] ivan dot cubillas at xeridia dot com [2008-08-08 01:02:34]

The problem with the PHP WebService Client

We've a JAVA WebService Server which could have attached documents. When the PHP Client send the dates, the Server take it correctly, but when 
the server return it to the PHP Client, the client reply always that is not a XML valid document.

The problem could be than the JAVA Server adds (to this type of XML binary files)  the documentType head: xml+xop and the clean doesn't understand
this head as a XML document.

There is some possibility to solve this problem in the PHP Client without doing changes in the JAVA Server?

[#14] aeg at mallxs dot nl [2008-05-28 05:19:20]

SoapFault exception: [SOAP-ENV:Client] looks like we got no XML document

This error can have to reasons:
1: Your server script has some hidden output like spaces before or afher  <?php ... ?>  or echoing some text
2: You have a bug in your server script;
    resulting in a error message output

Test your server script by calling it direct  from the browser.
The result should be a clean output like :

?<SOAP-ENV:Envelope>
?<SOAP-ENV:Body>
?<SOAP-ENV:Fault>
  <faultcode>SOAP-ENV:Server</faultcode>
  <faultstring>Bad Request. Can't find HTTP_RAW_POST_DATA</faultstring>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

This tell's you there was a request but without data; This is OK
Now if you get the error when calling with your soap client;
remember that your server now will call other functions in the server.php script because it now has some data to process

[#15] nodkz at mail dot ru [2008-05-24 02:25:49]

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.

<?php

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);
        }
    }
}

// ------------------------------------------
//  ABSTRACT EXAMPLE
// ------------------------------------------

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;

// some actions

$PersonList->getAsSOAP();

$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()

上一篇: 下一篇: