The State of SOAP in PHP
Upcoming SlideShare
Loading in...5
×
 

The State of SOAP in PHP

on

  • 4,031 views

Presentation at PHP Barcelona 2009

Presentation at PHP Barcelona 2009

Statistics

Views

Total Views
4,031
Views on SlideShare
4,013
Embed Views
18

Actions

Likes
2
Downloads
57
Comments
0

3 Embeds 18

http://www.slideshare.net 11
http://tubemote.com 5
http://webcache.googleusercontent.com 2

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

The State of SOAP in PHP The State of SOAP in PHP Presentation Transcript

  • THE STATE OF SOAP IN PHP
  • David Zülke
  • David Zuelke
  • apologies
  • http://flic.kr/chrismetcalf/43098186/
  • http://flic.kr/waltjabsco/3598975570/
  • back from
  • ZendCon
  • ✈ ✈
  • ✈
  • http://en.wikipedia.org/wiki/File:München_Panorama.JPG
  • Founder
  • awesome
  • Lead Developer
  • @dzuelke
  • WHAT IS SOAP? And How Did It All Start?
  • original plan
  • talk
  •  dis is srs bsns
  • make
  • Kit tY Inc No lu t de d http://flic.kr/kevinsteele/230997861/
  • however
  • http://en.wikipedia.org/wiki/File:Flughafenkontrolle.jpg
  • risk
  • SHOOT ME IN THE FACE
  • WHAT IS SOAP? And How Did It All Start?
  • Data Exchange Protocol
  • XML-based
  • language independent
  • platform independent
  • typically used for RPC-style Web Services
  •  zomg lol
  • ORIGINS A Brief (and Wildly Inaccurate) History Lesson
  • < 1998
  • XML-RPC
  • XML-RPC sucks
  • 1998
  • Simple Object Access Protocol 1.0
  • 2003
  • not really simple
  • renamed
  • Simple Object Access Protocol
  • SOAP
  • SOAP 1.2
  • GLOSSARY Transports, Messages and WSDL
  • SOAP TRANSPORTS • Transports are used for message transmission • Most important ones: • HTTP/HTTPS • SMTP
  • Amazon
  • 100.000.000.000 SOAP requests
  • (per second)
  • Sharks
  • (with friggin’ laser beams attached to their heads)
  • Custom Socket Transport
  • MESSAGES <?xml version="1.0" encoding="UTF‐8"?> <SOAP‐ENV:Envelope   xmlns:SOAP‐ENV="http:// schemas.xmlsoap.org/soap/envelope/" • Wrapped in an <Envelope>   xmlns:ns1="http://agavi.org/ sampleapp" > • <Header>s and a <Body>   <SOAP‐ENV:Body>     <ns1:getProductResponse>       <product>         <id>123456</id> • Structure is identical for         <name>Red Stapler</name>         <price>3.14</price> Request and Response       </product>     </ns1:getProductResponse>   </SOAP‐ENV:Body> </SOAP‐ENV:Envelope>
  • but worry not
  • that’s the entire point of SOAP
  • WSDL document
  • describes
  • • the service • the operations • the data types
  • <?xml version="1.0" encoding="utf‐8"?> <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"  xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http:// schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/ encoding/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://agavi.org/ sampleapp/types" xmlns:asa="http://agavi.org/sampleapp"  name="AgaviSampleApplication" targetNamespace="http://agavi.org/sampleapp">   <wsdl:types>     <xsd:schema xmlns:soap‐enc="http://schemas.xmlsoap.org/soap/encoding/"  targetNamespace="http://agavi.org/sampleapp/types">       <xsd:complexType name="Product">         <xsd:sequence>           <xsd:element name="id" type="xsd:int"/>           <xsd:element name="name" type="xsd:string"/>           <xsd:element name="price" type="xsd:float"/>         </xsd:sequence>       </xsd:complexType>       <xsd:complexType name="ArrayOfProducts">         <xsd:complexContent>           <xsd:extension base="soap‐enc:Array">             <xsd:attribute ref="soap‐enc:arrayType"  wsdl:arrayType="tns:Product[]"/>           </xsd:extension>         </xsd:complexContent>       </xsd:complexType>     </xsd:schema>   </wsdl:types>   <wsdl:portType name="AgaviSampleApplicationPortType">     <wsdl:operation name="getProduct">       <wsdl:input message="asa:getProductRequest"/>       <wsdl:output message="asa:getProductResponse"/>
  • AN EXAMPLE So We Are All on the Same Page
  • $client = new SoapClient('http://acme.com/product.wsdl', array(   'exceptions' => true,   'trace' => true, )); try {   var_dump($client‐>listProducts()); } catch(SoapFault $e) {   // here be dragons } array   0 =>      object(stdClass)[3]       public 'id' => int 8172401       public 'name' => string 'TPS Report Cover Sheet' (length=22)       public 'price' => float 0.89   1 =>      object(stdClass)[4]       public 'id' => int 917246       public 'name' => string 'Weighted Companion Cube' (length=23)       public 'price' => float 129.99
  • by the way
  • I will not talk about non-WSDL modes
  • because using SOAP without a WSDL is stupid
  • SOAP CLIENTS If You Want To Consume Services OMNOMNOM SERVICE
  • BASICS $client = new SoapClient(   'http://acme.com/product.wsdl', // URL to WSDL 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
  • GETTING AVAILABLE FUNCS $client = new SoapClient('http://acme.com/product.wsdl', array(   'exceptions' => true,   'trace' => true, )); var_dump($client‐>__getFunctions()); array   0 => string 'Product getProduct(int $id)' (length=27)   1 => string 'ArrayOfProducts listProducts()' (length=30)
  • GETTING AVAILABLE TYPES $client = new SoapClient('http://acme.com/product.wsdl', array(   'exceptions' => true,   'trace' => true, )); var_dump($client‐>__getTypes()); array   0 => string 'struct Product {  int id;  string name;  float price; }' (length=55)   1 => string 'Product ArrayOfProducts[]' (length=25)
  • ADVANCED CONCEPTS Faults, Headers and Mappings
  • FAULT HANDLING $client = new SoapClient('http://acme.com/product.wsdl', array(   'exceptions' => true,   '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 :) }
  • SOAP HEADERS $client = new SoapClient('http://acme.com/product.wsdl', array(   'exceptions' => true,   '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();
  • CLASSMAPS class Product {   protected $id, $name, $price;   // imagine getters and setters here } $client = new SoapClient('http://acme.com/product.wsdl', array(   'exceptions' => true,   'trace' => true,   'classmap' => array(     'Product' => 'Product', // no namespace here, which can be problematic…   ), )); var_dump($client‐>getProduct(123456)); object(Product)[2]   protected 'id' => int 123456   protected 'name' => string 'Red Stapler' (length=11)   protected 'price' => float 3.14
  • TYPEMAPS • Used for custom serialization and deserialization • Needs two callbacks: • one for XML->PHP conversion • one for PHP->XML conversion • Only necessary in very, very rare cases
  • SOAP SERVERS Slightly More Complicated
  • A BASIC SERVER class ProductService {   public function getProduct($id) {     // witchcraft here     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();
  • you can also register functions instead of class methods
  • wanna know how?
  • RTFM :X
  • DEALING WITH HEADERS class ProductService {   public function getProduct($id) {     // witchcraft here     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();
  • PRODUCING FAULTS class ProductService {   public function getProduct($id) {     if($product = ProductFinder::retrieveById($id)) {       return $product;     } else {       return new SoapFault('Server', 'No such product');     }   }   public function listProducts() {     // more witchcraft here     return $products;   } }
  • MULTI-PART RETURN VALUES class ProductService {   public function getTwoThings() {     // rocket science here     return array($foo, $bar);   } }
  • LITTLE SECRETS Did You Know That ext/soap Supports...
  • <complexType name="ArrayOfProducts">   <element name="products" type="foo:Product" maxOccurs="unbounded" /> </complexType>
  • {http://xml.apache.org/xml-soap}Map
  • LITTLE DISAPPOINTMENTS Things That ext/soap Does Not Support...
  • DateTime objects
  • document/literal wrapped
  • DOS AND DON’TS Keep This in Mind
  • enable the SOAP_SINGLE_ELEMENT_ARRAYS feature
  • don’t use SoapServer::fault()
  • use the exceptions option
  • double-check soap_use_error_handler()
  • don’t use cookies or other forms of state, ever
  • FRAMEWORK HIGHLIGHTS Zend Framework & Agavi
  • ZEND FRAMEWORK • Zend_Soap_Client as a wrapper for SOAPClient • Zend_Soap_Server as a wrapper for SOAPServer • Zend_Soap_Wsdl for constructing WSDL documents • Zend_Soap_Autodiscover for automatic WSDL generation
  • Zend_Soap_Autodiscover generates WSDLs for you!
  • using PHPDoc comments
  • class AcmeProductService {   /**    * @param      int     The ID of 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(); // dumps a WSDL
  • also very nice for prototyping
  • but might get difficult with complex stuff
  • AGAVI • Re-use existing Actions for SOAP Services • Needs 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
  • Demo
  • SOAP VERSUS REST Your Thoughts Please
  • !e End
  • Questions?
  • THANK YOU! • Shoot me an E-Mail: david.zuelke@bitextender.com • Follow @dzuelke on Twitter • Slides will be online at http://talks.wombert.de/