To save yourself a couple days of heart-ache, if you are trying to access a Windows server using SOAP and it seems as though the parameters are not being passed through to the Windows server, it is because of a bug in PHP. Because if you examine the SOAP packets going out (with Wireshark), you'll see that the parameter names are there in the <soap:Body>, but they have no values.
So instead, you should use the NuSOAP class and it will work perfectly: http://sourceforge.net/projects/nusoap/
I hope this helps and saves you pulling out your hair over this issue. :)
Ryan - http://operation513.blogspot.com
SOAP
- 導入
- インストール/設定
- 定義済み定数
- SOAP 関数
- is_soap_fault — SOAP コールが失敗したかどうかを調べる
- SoapClient->__call — SOAP 関数をコールする (推奨されません)
- SoapClient->__construct — SoapClient コンストラクタ
- SoapClient->__doRequest — SOAP リクエストを実行する
- SoapClient->__getFunctions — SOAP 関数の一覧を返す
- SoapClient->__getLastRequest — 直近の SOAP リクエストを返す
- SoapClient->__getLastRequestHeaders — 直近の SOAP リクエストヘッダを返す
- SoapClient->__getLastResponse — 直近の SOAP レスポンスを返す
- SoapClient->__getLastResponseHeaders — 直近の SOAP レスポンスヘッダを返す
- SoapClient->__getTypes — SOAP 型の一覧を返す
- SoapClient->__setCookie — SOAP リクエストと共に送信されるクッキーを設定する
- SoapClient->__soapCall — SOAP 関数をコールする
- SoapFault->__construct — SoapFault コンストラクタ
- SoapHeader->__construct — SoapHeader コンストラクタ
- SoapParam->__construct — SoapParam コンストラクタ
- SoapServer->addFunction — SOAP リクエストによって処理される単一もしくはいくつかの関数を追加する
- SoapServer->__construct — SoapServer コンストラクタ
- SoapServer->fault — エラーを示す SoapServer フォールト を発行する
- SoapServer->getFunctions — 定義されている関数の一覧を返す
- SoapServer->handle — SOAP リクエストを処理する
- SoapServer->setClass — SOAP リクエストを処理するクラスを設定する
- SoapServer->setPersistence — SoapServer の持続モードを設定する
- SoapVar->__construct — SoapVar コンストラクタ
- use_soap_error_handler — SOAP エラーハンドラを使用して前の値を返すかどうかを設定する
SOAP
Ryan
29-Oct-2008 04:01
29-Oct-2008 04:01
beau dot scott at gmail dot com
23-Oct-2008 12:34
23-Oct-2008 12:34
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);
}
}
?>
Ryan
22-Oct-2008 03:21
22-Oct-2008 03:21
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.
ivan dot cubillas at xeridia dot com
08-Aug-2008 10:02
08-Aug-2008 10:02
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?
aeg at mallxs dot nl
28-May-2008 02:19
28-May-2008 02:19
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
nodkz at mail dot ru
24-May-2008 11:25
24-May-2008 11:25
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
/*
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);
}
}
}
// ------------------------------------------
// 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()
