+add a note
User Contributed Notes 30 notes
Norman Clarke <norman at dontblink dot com> ¶
19 years ago
Note that if you should need to set the timeout for your soap request, you can use ini_set to change the value for the default_socket_timeout. I previously used NuSOAP, whose soap client class has a timeout option, and it took me a while to figure out that PHP's soap uses the same socket options as everything else.
ckl at ecw dot de ¶
18 years ago
To debug a SOAP service using SoapServer(), a WSDL file and Zend Studio Client/Server, you have to append ?start_debug=1&debug_port=10000 to the service location:
--- snip ---
... method / service definition ....
<service name="SOAPService">
<port
name="SOAPServicePort"
binding="typens:SOAPServiceBinding">
<soap:address
location="$URL?start_debug=1&debug_port=10000"/>
</port>
</service>
--- snap ---
Darryl ¶
19 years ago
Having trouble passing complex types over SOAP using a PHP SoapServer in WSDL mode? Not getting decoded properly? This may be the solution you're looking for!
When using ComplexType in the schema portion of the WSDL file, You need use an additional step to tell PHP SOAP how to encode the objects. The first method would be to explicitely encapsulate the object in a SoapVar object - telling PHP to use generalized SOAP encoding rules (which encodes all ComplexTypes as Structs). This won't work, though, if the client is expecting the objects to be encoded according to the WSDL's schema. So, The actual way to do this is:
* First, define a specific PHP class which is actually just a data structure holding the various properties, and the appropriate ComplexType in the WSDL.
<?php
class MyComplexDataType {
public $myProperty1;
public $myProperty2;
}
?>
<complexType name="MyWSDLStructure">
<sequence>
<element name="MyProperty1" type="xsd:integer"/>
<element name="MyProperty2" type="xsd:string"/>
</sequence>
</complexType>
* Next, Tell the SoapServer when you initialize it to map these two structures together.
<?php
$classmap = array('MyWSDLStructure' => 'MyComplexDataType');
$server = new SoapServer("http://MyServer/MyService.wsdl", array('classmap' => $classmap))
?>
* Finally, have your method return an instance of your class directly, and let the SoapServer take care of encoding!
<?php
public function MySoapCall() {
$o = new MyComplexDataType();
$o->myProperty1 = 1;
$o->myProperty2 = "MyString";
return $o
}
?>
Anonymous ¶
17 years ago
when dealing with wsdl and flash soap with php
(not exactly php, but proper wsdl - took me hours to figure it to work properly in flash webservice)
when naming definitions,
don't use "tns:" but use "typens:"
makesure your "definitions/targetNamespace"
is same as your "soap:body" namespace
example: "urn:mynamespace"
makesure your "binding/type" is declared with "typens"
makesure your service/port/binding is set to 'typens:...'
if you did not do it properly, you will end up with
WSDL.UnrecognizedNamespace - in flash
but seems okay in php soapclient...
happy coding :)
hope this help you to save your time on the wsdl :)
kroesjnov at hotmail dot com ¶
17 years ago
If you dont want to manually maintain the classmap, make sure you use the same names for your PHP object classes and your WSDL complexTypes, and use the following code:
$classmap = array();
$tmpClient = new SoapClient("soapserver.wsdl");
foreach($tmpClient->__getTypes() as $type)
{
$array = split(" ", $type);
if($array[0] == "struct" && class_exists($array[1]))
{
$classmap[$array[1]] = $array[1];
}
}
unset($tmpClient);
$server = new SoapServer("soapserver.wsdl", array("classmap" => $classmap));
unset($classmap);
$server->setClass("someclass");
$server->handle();
dirk at waferthin dot com ¶
17 years ago
I hope this will save someone time. When developing and testing your SOAP server, remember to disable WSDL caching in BOTH client and server:
$ini = ini_set("soap.wsdl_cache_enabled", 0);
Dominik ¶
17 years ago
If you are working
- on localhost
- in WSDL mode
and encounter the following error when you try to connect the soap client with the soap server
Fatal error: Uncaught SoapFault exception: [HTTP] Could not connect to host...
then change "localhost" to "127.0.0.1" in your WSDL file:
<soap:address location='http://127.0.0.1/soap-server.php'/>
mini at freebsd dot org ¶
18 years ago
wokan at cox dot net is incorrect about the security of URI-passed values to HTTPS URIs. HTTPS connections are HTTP inside SSL -- all of the HTTP traffic, including the request, are encrypted.
Bob ¶
19 years ago
If you are scratching your head why NuSOAP not working on PHP 5.x , the reason is this built-in SOAP Extenstion uses same soapclient() class name as Nusoap.
replace 'soapclient' with 'soapclient_xxx' in nusoap.php and you are good to go...
jochen dot munz at municons dot com ¶
17 years ago
When encountering an error message like this
[faultstring] => Function ("yourMethod") is not a valid method for this service
although it is present in the WSDL etc., be aware that PHP caches the wsdl locally for better performance. You can disable the caching via php.ini/.htaccess completely or remove the cache file (/tmp/wsdl-.. if you are on Linux) to force regeneration of it.
ChrisB ¶
19 years ago
Heads up for anyone using PHP Soap + Sessions + PEAR DB classes.
Every time you make a call, via the soap client to your web service, your PEAR DB session is put to sleep and it doesnt by default wake upon the next request.
To fix this I simply called my particular database close call ifx_close() below my $soap->handle();
albert at jool dot nl ¶
17 years ago
A note for ppl who use certificates with SOAP under a Windows config: it seems to be required to give the full path to the certificate file - and don't prepend 'file://' :
<?php
$wsdl = "test.wsdl";
$local_cert = "c:\htdocs\mycert.pem";
$passphrase = "xyz";
$client = new SoapClient($wsdl, array('local_cert' => $local_cert, 'passphrase' => $passphrase);
?>
flobee at gmail dot com ¶
19 years ago
wow, actually a cool program and soap is new for me.
I found out some interessting things i can not debug because the scripts exit without any error messages or notes. :-(
you may have problems with the memory and/or especially on "shared servers" when server load is high.
sometimes the script does the job, sometimes it just stopping at any unknown point.
these are the steps my script does:
* get data from remote server ( ~ 4.5 MB)
* parsing requested object and store the data in a database.
the return with debug messages was intressting:
-> check Mem limit: 30M
-> $client = new new SoapClient($url_wsdl, $options);
-> Memory usage: 185888
-> $client->[requested_method_to_get_data]();
-> check: __getLastResponseHeaders() - after:
-> HTTP/1.1 200 OK // remote server is fine with me :-)
-> Content-Length: 4586742 // I got the data
-> check: Memory usage now: 23098872 // ups !!! this can't be true!!
so, and if now someone on the server takes the rest of RAM the walk thought the data breaks :-(
so, i need to store the xml tree ($client->client->__last_response) and parsing it by the classical way. (if you would request more RAM, you may get in trouble with the admin if you run a script like this more often! (on shared servers)
AL13N ¶
17 years ago
this might be helpful, as it took quite some time for me to find this out:
if you're using some .wsdl and there's a sequence that can be there more than once (ie: maxOccurs > 1), you can specify an non-associative array for it if you have more than 1 items OR you could just specify the one item if there is only one:
<?php
'items' => array(
array(
'itemId' => 5,
'name' => 'some name',
),
array(
'itemId' => 6,
'name' => 'some other name',
),
),
?>
this also works:
<?php
'items' => array(
'itemId' => 5,
'name' => 'some name',
),
?>
kucerar at hhmi dot org ¶
19 years ago
Here are 73 test cases that detail the kinds of schemas that PHP5 currently supports and the structures you are expected to plug into them for the return value from your services. Much better than trying to guess!
http://cvs.php.net/co.php/pecl/soap/tests/schema
You can cycle through the listings by changing the main index in the URL below, rather than go in and out of the pages
http://cvs.php.net/co.php/pecl/soap/tests/schema/schema052.phpt?r=1.2
I downloaded the whole thing with this, CVS might work too.
http://www.httrack.com/
With them all downloaded I just browse them with Textpad.
adm ¶
18 years ago
Wondering why the function you just added to your WSDL file is not available to your SOAP client? Turn off WSDL caching, which (as the documentation says) is on by default.
At the top of your script, use:
$ini = ini_set("soap.wsdl_cache_enabled","0");
nodkz at mail dot ru ¶
16 years ago
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()
rlee at melbournechapter dot net ¶
16 years ago
Just a note on "DTD not recognised..." faults. Check to make sure your wsdl file contains:
<?xml version ='1.0' encoding ='UTF-8' ?>
Also make sure you use full paths, to your service (in the wsdl, client and server)
...
<wsdlsoap:address location='http://www.mysite.com.au/web_services/myserver.php' />
...
<?php
// SOAP Server
$server = new SoapServer('http://www.mysite.com.au/web_services/hello.wsdl');
...
...
?>
<?php
// SOAP Client
$client = new SoapClient('http://www.mysite.com.au/web_services/hello.wsdl');
...
...
?>
FYI im no SOAP expert but I hope this helps someone out ;)
Drydenmaker ¶
16 years ago
Working with a third party service I got: "SOAP-ERROR: Parsing Schema: unexpected <text> in restriction"
Thought it would be worth it to share. What it is saying is that there is some text in an invalid place. C# seems to ignore it, and if you are using nusoap it doesn't notice it either. But what was causing my problem was something like:
<types>
<schema ...
<simpleType name="some type">
<restriction base="xsd:string">
<enumeration value="foo"/>;
</restriction>
</simpleType>
Note the semicolon (;). Filter that out and your good.
james at mercstudio dot com ¶
17 years ago
If you use wsdl,
makesure you define the input correctly.
if your method does not contain any input parameter,
you got to makesure that you:
- do not create the message tag for the input..
- do not put input within porttype / operation
- do not put input within binding / operation
if not, you will get the error:
[Client] looks like we got no XML
d***, took me several hours figuring that out...
brephophagist ¶
17 years ago
For those working from a wsdl full of complex types that just want a class structure to hang your code on and not worry about typing in long parameter lists (or creating a script to do so): wsdl2php is a wonderful time-saver. Gets a structure going so you can go in and add what validation and special data munging you need: http://www.urdalen.no/wsdl2php/
Big up yourself, Knut.
Olaf Krische ¶
18 years ago
If you use SSL with a cert and password authentication:
$wsdl = "https://ws.ecopatz.de/ProductInfo?wsdl";
$pass = 'a password';
$certFile = "./mycert.pem";
$client = new SoapClient($wsdl,
array(
'local_cert' => $certFile,
'passphrase' => $pass
)
);
If you have problems with the certfile like this:
Warning: SoapClient::__construct(): Unable to set local cert chain file `./mycert.pem'; Check that your cafile/capath settings include details of your certificate and its issuer in productinfo.php on line 27
then the certFile is probably in the "wrong format" (the wrong format for php maybe). It worked for me, when i appended the content of the private key file and the certificate file to a single file "mycert.pem":
cat mycert.key >mycert.pem # mycert.key was the private key
cat mycert.crt >>mycert.pem # mycert.crt was the signed certificate
Thanks to an author somewhere, who pointed to "curl --cert", where this little "so unimportant" dependency has been mentioned.
nico ¶
18 years ago
If you want to build a Soap Server for Microsoft Office's client (like Microsoft Office Research Service) you need to rewrite SOAP's namespaces :
<?php
// (...)
$server = new SoapServer($wsdl, array('uri' => $uri, 'classmap' => $classmap));
$server->setClass($class);
function callback($buffer)
{
$s = array('<ns1:RegistrationResponse>', 'ns1:', 'xmlns:ns1="urn:Microsoft.Search"');
$r = array('<RegistrationResponse xmlns="urn:Microsoft.Search">', '', '');
return (str_replace($s, $r, $buffer));
}
ob_start('callback');
$server->handle();
ob_end_flush();
// (...)
?>
There are a complete example at this URL : http://touv.ouvaton.org/article.php3?id_article=104