- PHP 手册
- 函数参考
- Web 服务
- SOAP
- SoapClient
SoapClient::SoapClient
(PHP 5, PHP 7)
SoapClient::SoapClient — SoapClient constructor
说明
public SoapClient::SoapClient ( mixed$wsdl
[, array $options
] )
This constructor creates SoapClient objects in WSDL or non-WSDL mode.
参数
-
wsdl
-
URI of the WSDL file or
NULL
if working in non-WSDL mode.Note:
During development, WSDL caching may be disabled by the use of the soap.wsdl_cache_ttl php.ini setting otherwise changes made to the WSDL file will have no effect until soap.wsdl_cache_ttl is expired.
-
options
-
An array of options. If working in WSDL mode, this parameter is optional. If working in non-WSDL mode, the location and uri options must be set, where location is the URL of the SOAP server to send the request to, and uri is the target namespace of the SOAP service.
The style and use options only work in non-WSDL mode. In WSDL mode, they come from the WSDL file.
The soap_version option should be one of either
SOAP_1_1
orSOAP_1_2
to select SOAP 1.1 or 1.2, respectively. If omitted, 1.1 is used.For HTTP authentication, the login and password options can be used to supply credentials. For making an HTTP connection through a proxy server, the options proxy_host, proxy_port, proxy_login and proxy_password are also available. For HTTPS client certificate authentication use local_cert and passphrase options. An authentication may be supplied in the authentication option. The authentication method may be either
SOAP_AUTHENTICATION_BASIC
(default) orSOAP_AUTHENTICATION_DIGEST
.The compression option allows to use compression of HTTP SOAP requests and responses.
The encoding option defines internal character encoding. This option does not change the encoding of SOAP requests (it is always utf-8), but converts strings into it.
The trace option enables tracing of request so faults can be backtraced. This defaults to
FALSE
The classmap option can be used to map some WSDL types to PHP classes. This option must be an array with WSDL types as keys and names of PHP classes as values.
Setting the boolean trace option enables use of the methods SoapClient->__getLastRequest, SoapClient->__getLastRequestHeaders, SoapClient->__getLastResponse and SoapClient->__getLastResponseHeaders.
The exceptions option is a boolean value defining whether soap errors throw exceptions of type SoapFault.
The connection_timeout option defines a timeout in seconds for the connection to the SOAP service. This option does not define a timeout for services with slow responses. To limit the time to wait for calls to finish the default_socket_timeout setting is available.
The typemap option is an array of type mappings. Type mapping is an array with keys type_name, type_ns (namespace URI), from_xml (callback accepting one string parameter) and to_xml (callback accepting one object parameter).
The cache_wsdl option is one of
WSDL_CACHE_NONE
,WSDL_CACHE_DISK
,WSDL_CACHE_MEMORY
orWSDL_CACHE_BOTH
.The user_agent option specifies string to use in User-Agent header.
The stream_context option is a resource for context.
The features option is a bitmask of
SOAP_SINGLE_ELEMENT_ARRAYS
,SOAP_USE_XSI_ARRAY_TYPE
,SOAP_WAIT_ONE_WAY_CALLS
.The keep_alive option is a boolean value defining whether to send the Connection: Keep-Alive header or Connection: close.
The ssl_method option is one of
SOAP_SSL_METHOD_TLS
,SOAP_SSL_METHOD_SSLv2
,SOAP_SSL_METHOD_SSLv3
orSOAP_SSL_METHOD_SSLv23
.
错误/异常
SoapClient::SoapClient() will generate an
E_ERROR
error if the location and
uri options aren't provided in non-WSDL mode.
A SoapFault exception will be thrown if the
wsdl
URI cannot be loaded.
更新日志
版本 | 说明 |
---|---|
5.5.0 | New ssl_method option. |
5.4.0 | New keep_alive option. |
范例
Example #1 SoapClient::SoapClient() example
<?php
$client = new SoapClient("some.wsdl");
$client = new SoapClient("some.wsdl", array('soap_version' => SOAP_1_2));
$client = new SoapClient("some.wsdl", array('login' => "some_name",
'password' => "some_password"));
$client = new SoapClient("some.wsdl", array('proxy_host' => "localhost",
'proxy_port' => 8080));
$client = new SoapClient("some.wsdl", array('proxy_host' => "localhost",
'proxy_port' => 8080,
'proxy_login' => "some_name",
'proxy_password' => "some_password"));
$client = new SoapClient("some.wsdl", array('local_cert' => "cert_key.pem"));
$client = new SoapClient(null, array('location' => "http://localhost/soap.php",
'uri' => "http://test-uri/"));
$client = new SoapClient(null, array('location' => "http://localhost/soap.php",
'uri' => "http://test-uri/",
'style' => SOAP_DOCUMENT,
'use' => SOAP_LITERAL));
$client = new SoapClient("some.wsdl",
array('compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP));
$client = new SoapClient("some.wsdl", array('encoding'=>'ISO-8859-1'));
class MyBook {
public $title;
public $author;
}
$client = new SoapClient("books.wsdl", array('classmap' => array('book' => "MyBook")));
?>
User Contributed Notes 58 notes
up down 97 bhargav dot khatana at gmail dot com ¶9 years ago
It took me longer than a week to figure out how to implement WSSE (Web Service Security) headers in native PHP SOAP. There are no much resource available on this, so thought to add this here for community benefit.
Step1: Create two classes to create a structure for WSSE headers
<?php
class clsWSSEAuth {
private $Username;
private $Password;
function __construct($username, $password) {
$this->Username=$username;
$this->Password=$password;
}
}
class clsWSSEToken {
private $UsernameToken;
function __construct ($innerVal){
$this->UsernameToken = $innerVal;
}
}
?>
Step2: Create Soap Variables for UserName and Password
<?php
$username = 1111;
$password = 1111;
//Check with your provider which security name-space they are using.
$strWSSENS = "http://schemas.xmlsoap.org/ws/2002/07/secext";
$objSoapVarUser = new SoapVar($username, XSD_STRING, NULL, $strWSSENS, NULL, $strWSSENS);
$objSoapVarPass = new SoapVar($password, XSD_STRING, NULL, $strWSSENS, NULL, $strWSSENS);
?>
Step3: Create Object for Auth Class and pass in soap var
<?php
$objWSSEAuth = new clsWSSEAuth($objSoapVarUser, $objSoapVarPass);
?>
Step4: Create SoapVar out of object of Auth class
<?php
$objSoapVarWSSEAuth = new SoapVar($objWSSEAuth, SOAP_ENC_OBJECT, NULL, $strWSSENS, 'UsernameToken', $strWSSENS);
?>
Step5: Create object for Token Class
<?php
$objWSSEToken = new clsWSSEToken($objSoapVarWSSEAuth);
?>
Step6: Create SoapVar out of object of Token class
<?php
$objSoapVarWSSEToken = new SoapVar($objWSSEToken, SOAP_ENC_OBJECT, NULL, $strWSSENS, 'UsernameToken', $strWSSENS);
?>
Step7: Create SoapVar for 'Security' node
<?php
$objSoapVarHeaderVal=new SoapVar($objSoapVarWSSEToken, SOAP_ENC_OBJECT, NULL, $strWSSENS, 'Security', $strWSSENS);
?>
Step8: Create header object out of security soapvar
<?php
$objSoapVarWSSEHeader = new SoapHeader($strWSSENS, 'Security', $objSoapVarHeaderVal,true, 'http://abce.com');
//Third parameter here makes 'mustUnderstand=1
//Forth parameter generates 'actor="http://abce.com"'
?>
Step9: Create object of Soap Client
<?php
$objClient = new SoapClient($WSDL, $arrOptions);
?>
Step10: Set headers for soapclient object
<?php
$objClient->__setSoapHeaders(array($objSoapVarWSSEHeader));
?>
Step 11: Final call to method
<?php
$objResponse = $objClient->__soapCall($strMethod, $requestPayloadString);
?>
up
down
25
lsmith at php dot net ¶12 years ago
As noted in the bug report http://bugs.php.net/bug.php?id=36226, it is considered a feature that sequences with a single element do not come out as arrays. To override this "feature" you can do the following:
$x = new SoapClient($wsdl, array('features' =>
SOAP_SINGLE_ELEMENT_ARRAYS));
up
down
12
michael dot arnauts at gmail dot com ¶5 years ago
This doesn't seem to be documented, but when you want to use compression for your outgoing requests, you have to OR with the compression level:
<?php
$client = new SoapClient("some.wsdl",
array('compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP | 9));
?>
This can be really usefull if you want to send large amounts of data.
Source: https://bugs.php.net/bug.php?id=36283
up
down
16
Peter ¶5 years ago
if you need to use ws-security with a nonce and a timestamp, you can use this :
<?php
class WsseAuthHeader extends SoapHeader {
private $wss_ns = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd';
private $wsu_ns = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd';
function __construct($user, $pass) {
$created = gmdate('Y-m-d\TH:i:s\Z');
$nonce = mt_rand();
$passdigest = base64_encode( pack('H*', sha1( pack('H*', $nonce) . pack('a*',$created). pack('a*',$pass))));
$auth = new stdClass();
$auth->Username = new SoapVar($user, XSD_STRING, NULL, $this->wss_ns, NULL, $this->wss_ns);
$auth->Password = new SoapVar($pass, XSD_STRING, NULL, $this->wss_ns, NULL, $this->wss_ns);
$auth->Nonce = new SoapVar($passdigest, XSD_STRING, NULL, $this->wss_ns, NULL, $this->wss_ns);
$auth->Created = new SoapVar($created, XSD_STRING, NULL, $this->wss_ns, NULL, $this->wsu_ns);
$username_token = new stdClass();
$username_token->UsernameToken = new SoapVar($auth, SOAP_ENC_OBJECT, NULL, $this->wss_ns, 'UsernameToken', $this->wss_ns);
$security_sv = new SoapVar(
new SoapVar($username_token, SOAP_ENC_OBJECT, NULL, $this->wss_ns, 'UsernameToken', $this->wss_ns),
SOAP_ENC_OBJECT, NULL, $this->wss_ns, 'Security', $this->wss_ns);
parent::__construct($this->wss_ns, 'Security', $security_sv, true);
}
}
?>
and with your SoapClient do :
<?php
$client = new SoapClient("http://host/path");
$client->__setSoapHeaders(Array(new WsseAuthHeader("user", "pass")));
?>
works for me. based on a stackoverlfow post which only did the username and password, not the nonce and the timestamp
up
down
10
ryan dot jentzsch at gmail dot com ¶1 year ago
The documentation is wrong (version 7.1.12): A SoapFault exception will be thrown if the wsdl URI cannot be loaded.
What actually occurs -- even if wrapped in a try...catch(\Throwable $t) -- is an UNCATCHABLE fatal error is thrown.
up
down
10
tatupheba at gmail dot com ¶8 years ago
Hello folks!
A hint for developers:
When programming some soap server set the "soap.wsdl_cache_enabled" directive in php.ini file to 0:
soap.wsdl_cache_enabled=0
Otherwise it will give a bunch of strange errors saying that your wsdl is incorrect or is missing.
Doing that will save you from a lot of useless pain.
up
down
3
mkroese at eljakim dot nl ¶2 years ago
Do note that *contrary* to the ssl context option (http://php.net/manual/en/context.ssl.php#context.ssl.local-pk), `local_pk` is NOT a valid option. For the `local_cert` option, you should combine the private key with the certificate file.
Alternatively, if you do want to keep the private key and certificate file separate, you can create a stream context and pass that as the `context` option:
<?php
$context = stream_context_create([
'ssl' => [
'local_cert' => '/path/to/cert/file',
'local_pk' => '/path/to/private/key'
]]);
$client = new \SoapClient($wsdl, [
'context' => $context,
// other options
]);
up
down
1
Thomas Van Canegem ¶1 year ago
Further explanation regarding the cache options in WSDL mode:
WSDL_CACHE_MEMORY:
Will do a request and cache the WSDL's xml when instantiating the SoapClient object for the first time; invoked by EVERY request.
WSDL_CACHE_DISK:
Will do a request and cache the WSDL's xml the first time the SoapClient object is instantiated by A request.
up
down
10
simonlang at gmx dot ch ¶8 years ago
Example for a soap client with HTTP authentication over a proxy:
<?php
new SoapClient(
'service.wsdl',
array(
// Stuff for development.
'trace' => 1,
'exceptions' => true,
'cache_wsdl' => WSDL_CACHE_NONE,
'features' => SOAP_SINGLE_ELEMENT_ARRAYS,
// Auth credentials for the SOAP request.
'login' => 'username',
'password' => 'password',
// Proxy url.
'proxy_host' => 'example.com', // Do not add the schema here (http or https). It won't work.
'proxy_port' => 44300,
// Auth credentials for the proxy.
'proxy_login' => NULL,
'proxy_password' => NULL,
)
);
?>
Providing an URL to a WSDL file on the remote server (which as well is protected with HTTP authentication) didn't work. I downloaded the WSDL and stored it on the local server.
up
down
1
jon dot gilbert at net-entwicklung dot de ¶9 years ago
Note that creating a soap client for an invalid URL (you do test what happens, when a service is not available, right?) usually throws an exception which can be caught with try..catch. However, if xdebug is active you will get a fatal error, which obviously cannot be caught.
up
down
4
Anno v. Heimburg ¶11 years ago
> When using HTTP basic authentication, PHP will only send
> the credentials when invoking the service, not when
> fetching the WSDL.
The same goes for using an SSL client certficate, the SoapClient will only present the certificate on the actual remote call, not when getting the WSDL. The workaround is the same as above. HttpRequest works as expected.
up
down
3
jan at bestbytes dot de ¶10 years ago
You CAN get a wsdl, if basic authentication is required:
<?php
$login = 'bert';
$password = 'berts password';
$client = new SoapClient(
'http://' . urlencode($login) . ':' . urlencode($password) . '@www.server.com/path/to/wsdl',
array(
'login' => $login,
'password' => $password
)
);
?>
up
down
3
marcovtwout at hotmail dot com ¶8 years ago
If your WSDL file containts a parameter with a base64Binary type, you should not use base64_encode() when passing along your soap vars. When doing the request, the SOAP library automatically base64 encodes your data, so otherwise you'll be encoding it twice.
WSDL snipplet:
<element name="content" type="base64Binary" xmime:expectedContentTypes="*/*"/>
<?php
$string = 'data_you_want_to_send___like_xml_in_soap';
$soap_data = array(
'foo' => 'bar',
//'content' => base64_encode($string ) // don't do this
'content' => $string //do this
);
$response = $client->Send($soap_data);
?>
up
down
2
Jim Plush ¶13 years ago
As of version 5.0.4 you can now dynamically change your location even if you're using a wsdl
<?php
$client = new SoapClient("http://some.host.net/wsdl/somefile.wsdl",array(
"location" => 'myurl.com'));
?>
notice you can now use the "location" key.
This means you can have the same wsdl file not define a location until runtime which is great if you have a development test site or if you distribute your files to other companies.
Prior to this change you would have to ship a custom wsdl file to every client you had with their location hardcoded.
up
down
1
chris at phblock dot atNoSpam ¶7 years ago
this is the syntax of typemap (found at http://svn.php.net/viewvc/php/php-src/trunk/ext/soap/tests/typemap012.phpt?view=markup)
<?php
$options=Array(
'typemap' => array(
array("type_ns" => "http://schemas.nothing.com",
"type_name" => "soap",
"to_xml" => "some_funktion_name")
));
?>
up
down
1
cw at netresearch dot de ¶11 years ago
The "cache_wsdl" option takes constants like WSDL_CACHE_NONE or WSDL_CACHE_DISK that are listed on the "SOAP constants" page -> /manual/en/soap.constants.php
up
down
2
pgl at yoyo dot org ¶6 years ago
Note that if libxml_disable_entity_loader() has been called, you cannot specify a WSDL file - you'll get an error that PHP "failed to load external entity".
To resolve this, add
<?php
libxml_disable_entity_loader(false);
?>
Above any calls to instantiate SoapClient.
up
down
1
marcovtwout at hotmail dot com ¶8 years ago
Being new to SOAP, I was searching for a while to find out why my message was getting a response in soapUI, but not with my php code. The specific service I was addressing gives a HTTP 202 Accepted on success (no response), but returns a SOAP message on errors.
Situation:
Using an (authenticated) client connection, and a WDSL file, SOAP calls with type "One-Way" don't give a response header, even though a response is expected.
Solution:
When calling the client constructor, set SOAP_WAIT_ONE_WAY_CALLS in the $options['features'].
up
down
1
php at sowen dot de ¶13 years ago
If you're using CLI and there are multiple IP addresses available for outgoing SOAP-requests, try this "secret" to set outgoing IP:
e.g. for local IP 10.1.4.71:
$opts = array('socket' => array('bindto' => '10.1.4.71:0'));
$context = stream_context_create($opts);
$client = new SoapClient(null, array('location'=>'http://...','uri' => '...','stream_context' => $context));
You can also set other options for the stream context, please refer to this page:
Appendix M: http://www.php.net/manual/en/wrappers.php
Bye,
Nils Sowen
up
down
1
Arjan van Bentem ¶13 years ago
When using HTTP basic authentication, PHP will only send the credentials when invoking the service, not when fetching the WSDL.
To solve this, one needs to fetch the WSDL manually (or using PHP, of course!) and store it on the file system. Obviously, the first parameter for SoapClient(..) then needs to refer to that local copy.
Alternatively, the user annotations at http://nl3.php.net/manual/en/ref.soap.php state that one could encode the login and password into the URL as well.
See http://bugs.php.net/bug.php?id=27777
up
down
1
meltir at meltir dot com ¶9 years ago
To those fighting with NTLM authenticated proxy servers, here's a solution I'm using atm:
<?php
/**
* A child of SoapClient with support for ntlm proxy authentication
*
* @author Meltir <meltir@meltir.com>
*
*/
class NTLM_SoapClient extends SoapClient {
public function __construct($wsdl, $options = array()) {
if (empty($options['proxy_login']) || empty($options['proxy_password'])) throw new Exception('Login and password required for NTLM authentication!');
$this->proxy_login = $options['proxy_login'];
$this->proxy_password = $options['proxy_password'];
$this->proxy_host = (empty($options['proxy_host']) ? 'localhost' : $options['proxy_host']);
$this->proxy_port = (empty($options['proxy_port']) ? 8080 : $options['proxy_port']);
parent::__construct($wsdl, $options);
}
/**
* Call a url using curl with ntlm auth
*
* @param string $url
* @param string $data
* @return string
* @throws SoapFault on curl connection error
*/
protected function callCurl($url, $data) {
$handle = curl_init();
curl_setopt($handle, CURLOPT_HEADER, false);
curl_setopt($handle, CURLOPT_URL, $url);
curl_setopt($handle, CURLOPT_FAILONERROR, true);
curl_setopt($handle, CURLOPT_HTTPHEADER, Array("PHP SOAP-NTLM Client") );
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_POSTFIELDS, $data);
curl_setopt($handle, CURLOPT_PROXYUSERPWD,$this->proxy_login.':'.$this->proxy_password);
curl_setopt($handle, CURLOPT_PROXY, $this->proxy_host.':'.$this->proxy_port);
curl_setopt($handle, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
$response = curl_exec($handle);
if (empty($response)) {
throw new SoapFault('CURL error: '.curl_error($handle),curl_errno($handle));
}
curl_close($handle);
return $response;
}
public function __doRequest($request,$location,$action,$version,$one_way = 0) {
return $this->callCurl($location,$request);
}
}
?>
Requires curl and could be extended, but it works for my simple needs.
up
down
0
psy at psyberware dot com ¶3 months ago
If you try to use a 'stream_context' option to set additional HTTP headers, you should be aware of a couple of things.
First, even if you are using a https URL, the 'header' will be pulled from the 'http' section:
$context = stream_context_create([
'https' => [
'header' => 'Test: this will be ignored'
],
'http' => [
'header' => 'Test: this will be used'
]
]);
Second, there are a number of headers that are ignored, and will never be used. Check the underlying C source file soap/php_http.c and search for "skip some predefined headers" for a list. This is the reason some people report problems trying to set Host, Authorization, and other headers in certain situations.
up
down
0
Flaviu ¶11 months ago
When using classmap, the class constructors are NOT called.
If you want to do additional "magic", you can use the __set() / __get() combo.
Register a class with a "container" property alone and use the 2 magic methods.
Have fun
up
down
0
fschmidt at informatik dot uni-leipzig ¶2 years ago
In local_cert, the order of the certificates is relevant. After the key, first add the client certificate, then the rest of the chain. Offering the certificate chain before the client cert or only adding it to the system capath will result in an "alert unknown ca".
up
down
0
cdesully at webslicer dot com ¶3 years ago
I found a good use for typemap. When using classmap any xml tags that had attributes, attribute values were not captured, so a typemap allows you to override how a class gets implemented and being able to get any attributes not previously captured.
<ItemList>
<Item productId="1234">
<feature>red</feature>
</Item>
<Item productId="5678">
<feature>blue</feature>
</Item>
</ItemList>
<?php //semi-pseudo code
namespace ExampleNS;
class ItemList {
public $item = [];
}
class Item {
public $productId;
public $feature;
}
class Service {
public function __construct(){
$options = [
'classmap' => [
'ItemList' => 'ExampleNS\ItemList',
'Item' => 'ExampleNS\Item'
],
'typemap'=>[
'type_ns' => 'http://some.wsdl.ns/sdo',
'type_name' => 'Item',
'from_xml' => [__CLASS__,'newConversion']
]
];
}
public function newConversion($xml){
return simplexml_load_string($xml);
//or more appropriately dig into the simplexml object and
//instantiate the correct classes intended to be defined and
//return those
}
}
?>
up
down
0
omidkosari at yahoo dot com ¶3 years ago
To solve the problem with a lot of FIN_WAIT2 or CLOSE_WAIT , you should use the option keep_alive=false
up
down
0
info at nospam x valiton x com ¶4 years ago
CAUTION:
I had quite a bit of trouble trying to make a request with fopen through a proxy to a secure url. I kept getting a 400 Bad Request back from the remote host. It was receiving the proxy url as the SNI host. In order to get around this I had to explicity set the SNI host to the domain I was trying to reach. It's apparently the issue outlined in this bug:
https://bugs.php.net/bug.php?id=63519
<?php
$domain = parse_url($file, PHP_URL_HOST);
$proxy_string = "tcp://" . WP_PROXY_HOST . ":" . WP_PROXY_PORT;
$opts = array(
'http' => array( 'proxy' => $proxy_string ),
'ssl' => array( 'SNI_enabled' => true, 'SNI_server_name' => $domain));
$context = stream_context_create($opts);
$handle = fopen( $file, 'r', false, $context );
?>
src:
http://php.net/manual/en/context.http.php#114314
up
down
0
champetier dot etienne at gmail dot com ¶4 years ago
When using classmap, never put a fully qualified classname (starting with \)
there is a bug (https://bugs.php.net/bug.php?id=69280)
up
down
0
softontherocks at gmail dot com ¶4 years ago
I posted in this URL http://softontherocks.blogspot.com/2014/02/web-service-soap-con-php.html a full example of a nusoap web service.
There is defined the server and the client who calls the web service.
I hope it would be useful for you.
up
down
0
joshua at wiredrive dot com ¶4 years ago
As of 5.5, ssl_method defaults to SOAP_SSL_METHOD_SSLv23. Just wanted to add this because it was not explicitly specified above.
up
down
0
tolean dot dj at gmail dot com ¶5 years ago
Here's a function for easier debugging:
<?php
function soapDebug($client){
$requestHeaders = $client->__getLastRequestHeaders();
$request = prettyXml($client->__getLastRequest());
$responseHeaders = $client->__getLastResponseHeaders();
$response = prettyXml($client->__getLastResponse());
echo '<code>' . nl2br(htmlspecialchars($requestHeaders, true)) . '</code>';
echo highlight_string($request, true) . "<br/>\n";
echo '<code>' . nl2br(htmlspecialchars($responseHeaders, true)) . '</code>' . "<br/>\n";
echo highlight_string($response, true) . "<br/>\n";
}
$client = new SoapClient(null, array(
'location' => 'http://sita.local/_mpay/server.php',
'uri' => 'http://sita.local/_mpay/',
'trace' => 1,
));
$result = $client->__soapCall('getDate', array('format' => 'Y-m-d H:i:s'));
soapDebug($client);
?>
up
down
0
francesco [at] paladinux [dot] net ¶6 years ago
Where you have the problem of
"looks like we got no XML document SoapClient", really the real problem is the xml code from remote server is not clear (after last tag is possible that you have space or other caracter that the your supplier of service have lost : no one is perfect!)
I've read some solution, like here, but you must to know that is possible, that is possible that the remote server don't wrong, and the "surplus" (latin word for added values) is needed.
In particolar with axis Java server, is possible that the configuration of server is needed and the "surplus" is one or more attachments...
The solution is 3:
1) contact your supplier if is possible to remove caracter if is an error (good luck! ;) )
2) use another class like nusoap resolve the problem (but has other problem!)
3) this technical solution:
when call the wsdl be sure that the option trace and exceptions are setted (the first true and the second false)
<?php
$SoapClient = new SoapClient(NULL,
array(
....
'trace' => 1,
'exceptions' => 0
)
?>
(if you don't do that you can't use the __getLastResponse)
Now You can do the request and use __getLastResponse() to obtain all the part..
<?php
$result = $SoapClient -> problematicCall($par);
?>
After all you obtain a variable like that:
-----=_Part_9325_126764118.1363377774664
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: binary
Content-Id: <1C06F7FBA057796C5A6185605F9F93E4>
<?xml version="1.0" encoding="utf-8"?><...etc ><?xml version="1.0" encoding="UTF-8"?>
<MESSAGGIO>
<DA>MI</DA>
<A>PALADINUX</A>
<ID>12345</ID>
<TIPODOC>RC</TIPODOC>
<RISPOSTA>
</MESSAGGIO>
</rxproblematicCallReturn></ns1:rxCatalogoMaterialiResponse></soapenv:Body></soapenv:Envelope>
------=_Part_9325_126764118.1234567890123
Content-Type: application/zip
Content-Transfer-Encoding: binary
Content-Id: <43E91F7E7PALADINUXE07BF041A7BAC9>
-------------------------
Is easy understand if the added part is needed or not!
Now you can explode all the part and parse!
Hope this can help you.See ya in the cyberspace!
up
down
0
ale dot comp_06 at xox dot ch ¶6 years ago
If your service is protected through basic http authentication and you're not using wsdl, you will have to put the login in the SoapClient's option:
<?php
$client = new SoapClient(
null,
array(
'soap_version' => SOAP_1_2,
'location' => ...
...,
'login' => 'username',
'password' => '*******',
)
);
?>
up
down
0
Chris Gunawardena ¶7 years ago
To monitor SOAP calls in and out of a unix server:
sudo tcpdump -nn -vv -A -s 0 -i eth0 dst or src host xxx.xxx.xxx.xxx and port 80
And always use 'cache_wsdl' => WSDL_CACHE_NONE
up
down
0
willem dot stuursma at hyves dot nl ¶8 years ago
If you want to use classes in a different namespace in your classmap, just use the backslash in the the target class name.
Example:
<?php
$classmap = array('result' => 'MyNamespace\\Result');
?>
You need to specify the backslash twice because it is the escape character in strings.
up
down
0
Asaf Meller ¶8 years ago
a full working php .net soap configuration :
notes
1. web.config on .net server must work with basichttp binding.
2. paramaters to soap functions must be passed as :
array ('parm1_name'=>'parm1_value',
'parm2_name'=>'parm2_value'...)
<?php
header('Content-Type: text/plain');
try {
$options = array(
'soap_version'=>SOAP_1_1,
'exceptions'=>true,
'trace'=>1,
'cache_wsdl'=>WSDL_CACHE_NONE
);
$client = new SoapClient('http://www.example.com/end_point.wsdl', $options);
// Note where 'Get' and 'request' tags are in the XML
} catch (Exception $e) {
echo "<h2>Exception Error!</h2>";
echo $e->getMessage();
}
echo 'running HelloWorld :';
try {
$response=$client->HelloWorld();
}
catch (Exception $e)
{
echo 'Caught exception: ', $e->getMessage(), "\n";
}
print_r($response);
?>
good luck !
Asaf.
up
down
0
titan at phpdevshell dot org ¶8 years ago
It should be noted that if you receive a return error : 'Object reference not set to an instance of an object.'. This could be due to something as simple as passing the incorrect parameters. When you look at this XML:
<Get xmlns="http://example.com">
<request>
<CustomerId>string</CustomerId>
<From>dateTime</From>
<To>dateTime</To>
</request>
</Get>
Your code should look something like this:
<?php
try {
$options = array(
'soap_version'=>SOAP_1_2,
'exceptions'=>true,
'trace'=>1,
'cache_wsdl'=>WSDL_CACHE_NONE
);
$client = new SoapClient('http://example.com/doc.asmx?WSDL', $options);
// Note where 'Get' and 'request' tags are in the XML
$results = $client->Get(array('request'=>array('CustomerId'=>'1234')));
} catch (Exception $e) {
echo "<h2>Exception Error!</h2>";
echo $e->getMessage();
}
$results = $client->Get(array('request'=>array('CustomerId'=>'842115')));
?>
up
down
1
alex on reutone comma com ¶10 years ago
To connect PHP SOAP to MS SOAP (CRM/EXCHANGE/...) I have created some classes using the explanation below and in other places.
www.reutone.com/heb/articles.php?instance_id=62&actions=show&id=521
up
down
0
tim at tdinternet dot com ¶8 years ago
PHP 5.2.11 seems to not be very picky about the correctness of a WSDL.
Other SOAP clients were complaining about schema and namespace issues, while PHP's SoapClient worked completely fine. Fixing those issues for the other clients however broke PHP's SoapClient to the point where objects being passed to the SOAP method were becoming empty arrays on the server side.
Lesson learned: some elements were being prefixed with xsd: and others were not -- make absolutely sure your WSDL is correct and consistent (I'm using a tweaked WSDL_Gen.php).
up
down
0
james dot ellis at gmail dot com ¶8 years ago
I was having troubles getting responses from a Coldfusion SOAP server, with no obvious issues in the SoapClient used.
Eventually I found that the server was only accepting SOAP 1.1 requests and not 1.2. Not sure if this is a system wide Coldfusion setting but if you hit the same wall, try setting the SoapClient option "soap_version" to the constant SOAP_1_1 (which is the default but mine was defaulting to 1.2 as the client was being reused for another service)
up
down
0
ajcartmell at fonant dot com ¶8 years ago
There seems to be a problem with specifying empty strings for proxy_host and proxy_port options in recent versions of PHP (from a version later than 5.2.9, and equal to or earlier than 5.2.11).
Supplying empty string values for proxy_host and proxy_port causes "host not found" type errors: supplying NULL or FALSE works fine.
up
down
0
eric dot caron at gmail dot com ¶9 years ago
Though pointed out by jan at bestbytes, and discussed in bug #27777, one common source of the "Parsing WSDL: Couldn't find <definitions>" error is from trying to access a WSDL that is protected by HTTP authentication. Passing the login/password in the 2nd parameter doesn't always work; so if you encounter this error message and are trying to access a protected WSDL file, try passing the username and password in with the first parameter.
up
down
0
Anonymous ¶9 years ago
I had to struggle with a rather strange behavior when trying to consume standard Parlay X web services with no success. However, I found a remedy to my problem.
The problem which I faced was about an erroneous invalid HTTP basic authentication request sent to the web service. Although I was sending the right credentials, I was getting an authentication error. It turns out that PHP was sending HTTP requests to another endpoint which is not exposed directly through the web service and that end point does not require authentication.
My remedy for that issue was by using this simple lines in the example of using sendSms Paraly-X method.
First, creating a soap client without any HTTP authentication options:
<?php
$client = new SoapClient($wsdl_url);
?>
The above request will cache the wsdl in the /tmp directory. Immediately after this construction we create another soap client, this time with HTTP authentication options:
<?php
try {
$client = new SoapClient($wsdl_url, array('login' => "griffin",
'password' => "password"));
} catch (Exception $e) {
printf("Error:sendSms: %s\n",$e->__toString());
return false;
}
?>
Now it should work without any problem. Without the second call, PHP will call sendSms without credentials resulting in a failed attempt due to missing authentication information. I found this procedure to be the simplest.
This process should be done every time the cached wsdl expires, or simply a one can increase the time-to-live for the cached wsdl from php.ini
up
down
0
sloloem at gmail dot com ¶9 years ago
I had an issue figuring out the use of classmap that took me quite a while to figure out. I was assuming the WSDL type the docs were referring to was the name of the element being returned in the SOAP, so like,
<ns1:node id="8675309" />
and I was wondering why mapping
'classmap'=>array('node'=>'MyNode')
did nothing.
That's because in my WSDL I defined node as:
<xsd:element name="node" type="tns:nodeType" />
The classmap I needed was:
'classmap'=>array('nodeType'=>'MyNode')
I was able to find the type names using SoapClient->__getTypes()
Later, I realized where I could look inside the WSDL for the typename I needed.
I dunno if I missed something painfully obvious but maybe this can clear up some of the docs.
up
down
0
Jon ¶10 years ago
We've had some problems using SoapClient connecting to an external server via Microsoft ISA (presently v.2006 but this may apply to other versions too). We supply the proxy_host, proxy_port, proxy_login and proxy_password but the ISA server reports the login in its logs as "anonymous".
Our sysadmin believes this is because PHP is not supplying NTLN information (Windows security protocol) in the correct format (and whether it should work with proprietary proxies is of course another debate). We'd tried "username", "DOMAIN\username" to no effect. The solution is to add an exception in the ISA server for the target hostname/IP; null can then be supplied for proxy_login and proxy_password and the connection should then work as expected.
On a slightly related note, if you are having problems make sure the port number is supplied as an integer. Some versions of PHP will not use the proxy with SoapClient if the port number is supplied as a string.
up
down
0
info at nicksilvestro dot net ¶10 years ago
For anyone having trouble with ArrayOf_xsd_string and getting an error similar to 'No deserializer defined for array type {http://www.w3.org/2001/XMLSchema}string'
Try using the 'features' param, set to SOAP_USE_XSI_ARRAY_TYPE - this makes sure the correct deserializer is used.
eg,
<?php
$client = new SoapClient("some.wsdl", array('features' => SOAP_USE_XSI_ARRAY_TYPE));
?>
up
down
0
sniper ¶10 years ago
i was looking for a good example and couldnt find one,
finally found it somewhere(forgot where) i think this is
the best example to make a soap request with multiple params
$params->AWSAccessKeyId = AMAZON_API_KEY;
$params->Request->SearchIndex = 'Books';
$params->Request->Keywords = 'php5 oop';
$amazon = new SoapClient('http://webservices.amazon.com
/AWSECommerceService/AWSECommerceService.wsdl');
$result = $amazon->itemSearch($params);
up
down
0
taras dot dot dot di at gmail dot com ¶10 years ago
This took me a while to figure out.
As described at the bottom of here: http://bugs.php.net/bug.php?id=38703
having xdebug may interfere with the constructor throwing exceptions
up
down
0
naugtur at gmail dot com ¶10 years ago
SoapFault exception: [Client] looks like we got no XML document in <document> has been already mentioned to occur when your server outputs something before <?xml ... > tag.
For all those having problems with that, and no access to the server code:
This is how to make a proxy that would clean responses for You
<?php
/**
* Simple class taken from a note by James Ellis [in __doRequest() page of manual]
*/
class Proxy_Client extends SoapClient {
protected $cacheDocument = "";
public function __construct($wsdl, $options) {
parent::__construct($wsdl, $options);
}
/**
* SetCacheDocument() sets the previously cached document contents
*/
public function SetCacheDocument($document) {
$this->cacheDocument = $document;
}
/**
* __doRequest() overrides the standard SoapClient to handle a local request
*/
public function __doRequest() {
return $this->cacheDocument;
}
}
//put this code in your function or wherever You have all required variables set
$client = new SoapClient($wsdl_url,$settings_array);
$void=$client->$method($params); //call this to get response from server
$response_string=$client->__getLastResponse();
//this part removes stuff
$start=strpos($response_string,'<?xml');
$end=strrpos($response_string,'>');
$response_string=substr($response_string,$start,$end-$start+1);
//get your proxy prepared
$proxy = new Proxy_Client($wsdl_url,$settings_array);
//and fill it with the server's response
$proxy->SetCacheDocument($response_string);
$and_finally_the_result_is=$proxy->$method($params);
print_r($and_finally_the_result_is); //this allows You to see what's there
?>
$method is the method's name eg. $method='getVersion';
$params - typical params for a soap method
up
down
0
david at globulebleu dot com ¶10 years ago
When using classmap option to map the SOAP results to a class, the constructor
of the object you've mapped to is not called.
$client = new SoapClient("url_to_wsdl",
array('classmap' => array('contact' => "Contact"));
$params = array("1");
$contact = $client->__soapCall("get_contact", $params);
Expected result:
A contact object that has properties initialized (i.e. db connections,
....).
Actual result:
A contact object without the properties.
Thanks for your help.
David Georges.
up
down
0
james dot ellis at gmail dot com ¶11 years ago
A note regarding boolean values that may seem obvious on reflection but could be a gotcha for some:
Seeing a SOAP request example with <SomeBooleanParam>true</SomeBooleanParam> may lead you to pass in string "true" or "false" as the parameter, which is incorrect - the correct method is to use boolean data types.
<?php
$client = new SoapClient($wsdl,$options);
$method = "DoSomething";
$params = new stdClass;
$params->SomeBooleanParam = TRUE;
$client->$method($params);
/**
simplified request snippet would be
<SomeBooleanParam>true</SomeBooleanParam>
**/
//this will also be correct, but not for the right reasons:
$params->SomeBooleanParam = "true";
$client->$method($params);
/**
simplified request snippet would be
<SomeBooleanParam>true</SomeBooleanParam>
**/
//this is where you may be wondering what is going on
$params->SomeBooleanParam = "false";
$client->$method($params);
/**
simplified request snippet would be
<SomeBooleanParam>true</SomeBooleanParam>
**/
//you need to do this instead
$params->SomeBooleanParam = FALSE;
$client->$method($params);
/**
simplified request snippet would be
<SomeBooleanParam>false</SomeBooleanParam>
**/
?>
Hope that helps!
up
down
0
giosh94mhz ¶11 years ago
Oops!
I have written the wrong exception message in my last post.
The correct exception is:
SoapFault exception: [Client] looks like we got no XML document in <document>
up
down
0
matt_schiros at academicsuperstore dot com ¶12 years ago
When using classmap to map the SOAP results to a class, the constructor of the object you've mapped to is _not_ called. This applies to the PHP5 __construct() and the PHP4 ClassName() constructors.
up
down
0
Marius Mathiesen ¶13 years ago
I kept having a problem using an HTTP proxy with SOAP. The proxy_port parameter has to be an integer, ie. "proxy_port"=>"80" won't work, you'll have to use "proxy_port"=>80.
HTH,
Marius
up
down
0
jared at ws-db dot com ¶13 years ago
If you connect to a SoapServer, that has been created with session persistence, you can access the server's session id via SoapClient->_cookies[<session_id_name>][0]. This property becomes available after your first client method call.
I have only tested this with session.use_cookies=1.
up
down
0
Brian Grayless ¶14 years ago
Using a WSDL file is the way to go, however, for my particular application, the LOCATION:PORT needed to be dynamic
8288分类目录声明:本站部分文章来源于网络,版权属于原作者所有。如有转载或引用文章/图片涉及版权问题,请联系我们处理.我们将在第一时间删除!
联系邮箱:tsk@qq.com