Things that I've searched a lot for that might be useful to somebody:
If you are using Zend Studio, you can easily generate a wsdl file using the WSDL Generator if you document your code using PHPDOC.
One thing a lot of people are searching everywhere, is the way to pass/return an array of variables... In your PHPDOC block use the [] after the variable name like this
<?php
class SoapServer {
/**
* This is My Soap Server
* @param integer[] $a
* @param string[] $b
* @param bar[] $c
*/
public function foo ($a, $b, $c){
}
}
?>
This way, the function will require an array of integers for $a, an array of strings for $b and an array of objets of Class "bar" for $c
In the WSDL, you'll find something like this
<xsd:complexType name="barArray">
<xsd:complexContent>
<xsd:restriction base="soapenc:Array">
<xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="typens:bar[]"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="bar">
<xsd:all>
<xsd:element name="var1" type="xsd:boolean"/>
<xsd:element name="var2" type="xsd:integer"/>
<xsd:element name="var3" type="xsd:string"/>
</xsd:all>
</xsd:complexType>
I didn't define anywhere the barArray type, Zend's WSDL Generator generated it automatically...
If you are not using Zend you can generate the wsdl file manually.
Hope it helps someone
SoapServer->__construct()
(No version information available, might be only in CVS)
SoapServer->__construct() — SoapServer-Konstruktor
Beschreibung
Der Konstruktor erlaubt das Erzeugen eines SoapServer-Objekts in WSDL- oder nicht-WSDL-Modus.
Parameter-Liste
- wsdl
-
Wenn der WSDL-Modus verwendet werden soll, muss die URI auf eine WSDL-Datei verweisen. Ansonsten muss er auf NULL gesetzt werden und die uri vewendet werden.
- options
-
Erlaubt das Setzen der benutzten SOAP-Version (soap_version), der internen Zeichenkodierung (encoding), und URI (actor).
Die classmap Option kann genutzt werden, um WSDL-Typen auf PHP-Klassen abzubilden. Die Option muß ein Array sein mit den WSDL-Typen als Schlüssel und den PHP-Klassennamen als Wert.
Die Option typemap ist ein Array mit Typabbildungen. Jede Abbildung ist ein Array mit den Schlüsseln type_name, type_ns (Namespace URI), from_xml (callback akzeptiert einen String-Parameter) und to_xml (callback akzeptiert einen Objekt-Parameter).
Weitere Optionen sind features und cache_wsdl.
Beispiele
Beispiel #1 Beispiele
<?php
$server = new SoapServer("some.wsdl");
$server = new SoapServer("some.wsdl", array('soap_version' => SOAP_1_2));
$server = new SoapServer("some.wsdl", array('actor' => "http://example.org/ts-tests/C"));
$server = new SoapServer("some.wsdl", array('encoding'=>'ISO-8859-1'));
$server = new SoapServer(null, array('uri' => "http://test-uri/"));
class MyBook {
public $title;
public $author;
}
$server = new SoapServer("books.wsdl", array('classmap' => array('book' => "MyBook")));
?>
SoapServer->__construct()
29-Jul-2008 06:45
02-Feb-2008 01:48
This site helped me put it all together.
http://techblog.bronto.com/brontotechblog/2007/04/php_and_soap_he.html
My issue was I was trying the below example but missing parts in the wsdl. The above link filled in the pieces that I was missing so it all worked.
31-Oct-2007 12:42
In response to Timo, it is possible to access Soap Headers from the SoapServer class and call methods to handle them. Rather than treat them seperately, they are treated as part of the Soap request.
To pass approximately wss standard headers (note that I couldn't get attributes from the header tags without text preprocessing, so standards compliance failed me), first create the following class on the client:
<?php
/*
* Login credentials to be supplied as a SOAP header
* Class used to ensure Soap Head tags in correct format.
*/
class SoapHeaderUsernameToken
{
/** @var int Password */
public $Password;
/** @var int Username */
public $Username;
public function __construct($l, $p)
{
$this->Password = $p;
$this->Username = $l;
}
}
?>
Now, set the Soap Headers:
<?php
// Set the login headers
$wsu = 'http://schemas.xmlsoap.org/ws/2002/07/utility';
$usernameToken = new SoapHeaderUsernameToken($this->username, $this->password);
$soapHeaders[] = new SoapHeader($wsu, 'UsernameToken', $usernameToken);
?>
Next instantiate the client object, add the headers and make the call:
<?php
$client = new SoapClient( $wsdl);
$client->__setSoapHeaders( $soapHeaders );
$client->__soapCall( $method, $params );
?>
Moving to the Server, you'll handle the Soap call somewhat like:
<?php
// Instantiate server with relevant wsdl & class.
$server = new SoapServer( 'mysoapwsdl.wsdl' );
$server->setClass( 'mysoapclass' );
$server->handle();
?>
The key here is that the headers will be handled first by the server which will call the method mysoapclass::UsernameToken. The way we work this is the UsernameToken method authenticates the username / password combo and sets a protected class var. Then when the Soap Body is handled and the appropriate class method called, a check is made at the start of callable method to ensure authentication has been passed.
If the Soap auth header is missing, the soap body method will be called anyway so the check is essential in case a malevolent client deliberately leaves the headers off.
An example server class is below (missing various methods which I leave as an exercise to the reader to provide):
<?php
class mysoapclass {
/*
* Authentication function
* This is called by the Soap header of the same name. The function name is a Ws-security standard auth tag
* and corresponds to the header tag.
*
* @param string username
* @param string password
*/
public function UsernameToken( $username, $password ){
// Store username for logging
$this->Username = $username;
$auth = new $this->AuthClass( $username, $password, get_class($this) );
if( $auth->IsValid() ){
$this->Authenticated = true;
} else {
$this->ThrowSoapFault( 'auth' );
}
}
/*
* Test method
*/
public function felineResponse( $action ){
// Place this at the start of every exposed method
// This is because the SoapServer will attempt to call
// if no authentication headers are passed.
if(!$this->Authenticated){
$this->ThrowSoapFault( 'auth' );
}
if( $action == 'stroke' ){
return 'purr';
} elseif( $action == 'tease' ){
return 'hiss';
}
}
}
?>
This is a adaptation of stuff I found online somewhere...
11-Jul-2007 07:12
In response to jas [at] dansupport (dot) dk:
All you need to do is disable wsdl caching like so:
ini_set("soap.wsdl_cache_enabled", "0");
Then you don't need to delete any cache files.
30-May-2007 08:24
A general thing i've experienced with SOAP and which, for some reason, isn't mentioned in ANY tutorials I've read, is this: The server tends to cache the interface. This means that if you add a function you'll usually get errors that the function doesn't exist.
If your SOAP server is written in PHP just delete the cache files, usually located in /tmp, whenever you add a function, or modify the parameters. These are named wsdl-******something******
I hope this will spare someone the grief I've experienced with this.
03-Aug-2006 02:46
It is currently not possible to process soap headers from within a SoapServer instance. If soap headers are specified within a WSDL file, you have to extract the headers manually from the request.
For more information please see http://bugs.php.net/bug.php?id=38309
