describing the service array( // array of additional options for the client 'exceptions' => true, // throw SoapFault exceptions on errors 'trace' => true, // allow use of SoapClient::__getLast…() ) ); $allProducts = $client‐>listProducts(); // $allProducts contains return value
'trace' => true, )); try { $newThing = $client‐>createProduct(new stdClass()); } catch(SoapFault $e) { // could be a client‐side fault e.g. if fields are missing // or a server‐side fault if the server had any objections :) }
'trace' => true, )); $client‐>setSoapHeader( new SoapHeader('http://acme.com/soap/products', 'username', 'Chuck Norris') ); $client‐>setSoapHeader( new SoapHeader('http://acme.com/soap/products', 'password', 'r0undh0usek!ck') ); // headers will be sent along with the request $allProducts = $client‐>listProducts();
cases • Example: • xsd:long is mapped to PHP int, overflows on 32bit archs • Needs two callbacks: • one for XML->PHP conversion • one for PHP->XML conversion
. '</long>'; } function from_long_xml($xmlFragmentString) { return (string)strip_tags($xmlFragmentString); } $client = new SoapClient('http://acme.com/products.wsdl', array( 'typemap' => array( array( 'type_ns' => 'http://www.w3.org/2001/XMLSchema', 'type_name' => 'long', 'to_xml' => 'to_long_xml', 'from_xml' => 'from_long_xml', ), ), )); you can use any name for this wrapper tag
return $product; } public function listProducts() { // more witchcraft here return $products; } } $server = new SoapServer('/path/to/local/products.wsdl', array(/* options… */)); // register a class to instantiate that has all the methods $server‐>setClass('ProductService'); // alternative: use an existing instance $server‐>setObject(new ProductService()); // rock and roll $server‐>handle(); A BASIC SERVER
return $product; } public function listProducts() { // more witchcraft here return $products; } public function username($value) { // check if it's really chuck norris } public function password($value) { // check if he did a roundhouse kick } } $server = new SoapServer('/path/to/local/products.wsdl', array(/* options… */)); // register a class to instantiate that has all the methods $server‐>setClass('ProductService'); // rock and roll $server‐>handle(); DEALING WITH HEADERS
{ return $product; } else { return new SoapFault('Server', 'No such product'); } } public function listProducts() { // more witchcraft here return $products; } } PRODUCING FAULTS
name="parameters" type="apache‐enc:Map" /> </xsd:complexType> </xsd:schema> • Custom Apache Axis encoding style • be aware that it won’t offer good interoperability • Use any type for values, scalars for keys • Keys and values will use RPC encoding in the message
without a response declared • Both SoapClient and SoapServer will close the connection as soon as they can when calling such a method http://flic.kr/99996581@N00/1122331674/
be validated against the WSDL’s XML Schema • Unlike with RPC style services, such messages won’t contain the name of the called method anymore • Solution: wrap the message payload in an element that has the same name as the procedure you want to call • Not a problem in PHP, but you need to wrap/unwrap yourself
the product. * * @return Product The product object. * * @deprecated Call Joe from sales if you want to know details about a product… */ public function getProduct($id) { // witchcraft goes here return $product; } } $autodiscover = new Zend_Soap_AutoDiscover(); $autodiscover‐>setClass('AcmeProductService'); $autodiscover‐>handle(); // only dumps a WSDL, does not start a server!
some information about the service in WSDL format • WSDL auto-generated by the Routing • Requires basic knowledge of XML Schema and WSDL • Supports Document/Literal Wrapped for Servers