the state of soap in php

117
THE STATE OF SOAP IN PHP

Upload: david-zuelke

Post on 15-Jan-2015

5.615 views

Category:

Technology


1 download

DESCRIPTION

Presentation on SOAP at the PHPBenelux Conference 2010

TRANSCRIPT

Page 1: The State of SOAP in PHP

THE STATE OF SOAP IN PHP

Page 2: The State of SOAP in PHP

David Zülke

Page 3: The State of SOAP in PHP

David Zuelke

Page 4: The State of SOAP in PHP
Page 5: The State of SOAP in PHP

http://en.wikipedia.org/wiki/File:München_Panorama.JPG

Page 6: The State of SOAP in PHP

Founder

Page 8: The State of SOAP in PHP

Lead Developer

Page 10: The State of SOAP in PHP

@dzuelke

Page 11: The State of SOAP in PHP

WHAT IS SOAP?And How Did It All Start?

Page 12: The State of SOAP in PHP

original plan

Page 13: The State of SOAP in PHP

talk

Page 14: The State of SOAP in PHP
Page 15: The State of SOAP in PHP

make

Page 16: The State of SOAP in PHP

http://flic.kr/kevinsteele/230997861/

KittY NotIncluded

Page 17: The State of SOAP in PHP
Page 18: The State of SOAP in PHP

however

Page 19: The State of SOAP in PHP

Page 21: The State of SOAP in PHP

last week

Page 22: The State of SOAP in PHP

dis is srs bsns

Page 23: The State of SOAP in PHP

( )( )( )

Page 24: The State of SOAP in PHP

http://en.wikipedia.org/wiki/File:Flughafenkontrolle.jpg

Page 25: The State of SOAP in PHP

let him run away

Page 26: The State of SOAP in PHP
Page 28: The State of SOAP in PHP
Page 29: The State of SOAP in PHP

Page 30: The State of SOAP in PHP

NEIN NEIN NEIN NEIN

DAS IST VERBOTEN

Page 31: The State of SOAP in PHP

WHAT IS SOAP?And How Did It All Start?

Page 32: The State of SOAP in PHP

Data Exchange Protocol

Page 33: The State of SOAP in PHP

XML-based

Page 34: The State of SOAP in PHP

language independent

Page 35: The State of SOAP in PHP

platform independent

Page 36: The State of SOAP in PHP

typically used for RPC-style Web Services

Page 37: The State of SOAP in PHP

zomg lol

Page 38: The State of SOAP in PHP

ORIGINSA Brief (and Wildly Inaccurate) History Lesson

Page 39: The State of SOAP in PHP

< 1998

Page 40: The State of SOAP in PHP

XML-RPC

Page 41: The State of SOAP in PHP

XML-RPC sucks

Page 42: The State of SOAP in PHP

1998

Page 43: The State of SOAP in PHP

Simple Object Access Protocol 1.0

Page 44: The State of SOAP in PHP

2003

Page 45: The State of SOAP in PHP

not really simple

Page 46: The State of SOAP in PHP

renamed

Page 47: The State of SOAP in PHP

Simple Object Access Protocol

Page 48: The State of SOAP in PHP

SOAP

Page 49: The State of SOAP in PHP

SOAP 1.2

Page 50: The State of SOAP in PHP

GLOSSARYTransports, Messages and WSDL

Page 51: The State of SOAP in PHP

SOAP TRANSPORTS

• Transports are used for message transmission

• Most important ones:

• HTTP/HTTPS

• SMTP

Page 52: The State of SOAP in PHP

Amazon

Page 53: The State of SOAP in PHP

100.000.000.000 SOAP requests

Page 54: The State of SOAP in PHP

(per second)

Page 55: The State of SOAP in PHP

Sharks

Page 56: The State of SOAP in PHP

(with friggin’ laser beams attached to their heads)

Page 57: The State of SOAP in PHP

Custom Socket Transport and Serialization!

Page 58: The State of SOAP in PHP

MESSAGES

• Wrapped in <Envelope>

• <Header>s and a <Body>

• Structure is identical for Request and Response

<?xml version="1.0" encoding="UTF‐8"?><SOAP‐ENV:Envelope  xmlns:SOAP‐ENV="http://schemas.xmlsoap.org/soap/envelope/"  xmlns:ns1="http://agavi.org/sampleapp">  <SOAP‐ENV:Body>    <ns1:getProductResponse>      <product>        <id>123456</id>        <name>Red Stapler</name>        <price>3.14</price>      </product>    </ns1:getProductResponse>  </SOAP‐ENV:Body></SOAP‐ENV:Envelope>

Page 59: The State of SOAP in PHP

but worry not

Page 60: The State of SOAP in PHP

that’s the entire point of SOAP

Page 61: The State of SOAP in PHP

WSDL document

Page 62: The State of SOAP in PHP

describes

Page 63: The State of SOAP in PHP

• the service

• the operations

• the data types

Page 64: The State of SOAP in PHP

<?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"/>    </wsdl:operation>    <wsdl:operation name="listProducts">      <wsdl:output message="asa:listProductsResponse"/>    </wsdl:operation>  </wsdl:portType>  <binding name="AgaviSampleApplicationBinding" type="asa:AgaviSampleApplicationPortType">    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>    <wsdl:operation name="getProduct">      <soap:operation soapAction="http://agavi.org/sampleapp#getProduct"/>      <wsdl:input>        <soap:body namespace="http://agavi.org/sampleapp" use="literal"/>      </wsdl:input>      <wsdl:output>        <soap:body namespace="http://agavi.org/sampleapp" use="literal"/>      </wsdl:output>    </wsdl:operation>    <wsdl:operation name="listProducts">      <soap:operation soapAction="http://agavi.org/sampleapp#listProducts"/>      <wsdl:output>        <soap:body namespace="http://agavi.org/sampleapp" use="literal"/>      </wsdl:output>    </wsdl:operation>  </binding>  <service name="AgaviSampleApplicationService">    <port name="AgaviSampleApplicationPort" binding="asa:AgaviSampleApplicationBinding">      <soap:address location="http://services.acme.com/soap.php"/>    </port>  </service>  <wsdl:message name="getProductRequest">    <wsdl:part name="id" type="xsd:int"/>  </wsdl:message>  <wsdl:message name="getProductResponse">    <wsdl:part name="product" type="tns:Product"/>  </wsdl:message>  <wsdl:message name="listProductsResponse">    <wsdl:part name="products" type="tns:ArrayOfProducts"/>  </wsdl:message></wsdl:definitions>

Page 65: The State of SOAP in PHP

AN EXAMPLESo We Are All on the Same Page

Page 66: The State of SOAP in PHP

$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

Page 67: The State of SOAP in PHP

by the way

Page 68: The State of SOAP in PHP

I will not talk about non-WSDL modes

Page 69: The State of SOAP in PHP

using SOAP without a WSDL is a very bad idea

Page 70: The State of SOAP in PHP

SOAP CLIENTSIf You Want To Consume Services

OMNOMNOM SERVICE

Page 71: The State of SOAP in PHP

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

Page 72: The State of SOAP in PHP

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)

Page 73: The State of SOAP in PHP

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)

Page 74: The State of SOAP in PHP

ADVANCED CONCEPTSFaults, Headers and Mappings

Page 75: The State of SOAP in PHP

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 :)}

Page 76: The State of SOAP in PHP

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();

Page 77: The State of SOAP in PHP

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 XML 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

Page 78: The State of SOAP in PHP

TYPEMAPS

• Used for custom serialization and unserialization in rare 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

Page 79: The State of SOAP in PHP

TYPEMAP EXAMPLE: XS:LONG

function to_long_xml($longVal) {  return '<long>' . $longVal . '</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

Page 80: The State of SOAP in PHP

SOAP SERVERSSlightly More Complicated

Page 81: The State of SOAP in PHP

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();

A BASIC SERVER

Page 82: The State of SOAP in PHP

you can also register functions instead of class methods

Page 83: The State of SOAP in PHP

wanna know how?

Page 84: The State of SOAP in PHP

RTFM :X

Page 85: The State of SOAP in PHP

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();

DEALING WITH HEADERS

Page 86: The State of SOAP in PHP

again, it can’t tell headers from different namespaces apart

Page 87: The State of SOAP in PHP

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;  }}

PRODUCING FAULTS

Page 88: The State of SOAP in PHP

class ProductService {  public function getTwoThings() {    // rocket science here    return array($product1, $product2);  }}

MULTI-PART RETURN VALUES

<wsdl:message name="getTwoThingsRequest">  <wsdl:part name="id1" type="xsd:int"/>  <wsdl:part name="id2" type="xsd:int"/></wsdl:message><wsdl:message name="getTwoThingsResponse">  <wsdl:part name="firstThing" type="tns:Product"/>  <wsdl:part name="secondThing" type="tns:Product"/></wsdl:message>

list($p1, $p2) = $client‐>getTwoThings($id1, $id2));

Page 89: The State of SOAP in PHP

LITTLE SECRETSDid You Know That ext/soap Supports...

Page 90: The State of SOAP in PHP

<complexType name="ArrayOfProducts">  <element name="products" type="foo:Product" maxOccurs="unbounded" /></complexType>

XML SCHEMA ARRAYS

<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>

=

Page 91: The State of SOAP in PHP

HASHMAPS (W/ STRING KEYS)

<xsd:schema  xmlns:apache‐enc="http://xml.apache.org/xml‐soap">  <xsd:complexType name="MyHashmap">    <xsd:element      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

Page 92: The State of SOAP in PHP

ONE-WAY CALLS

• SOAP Operations may have only a request, 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/

Page 93: The State of SOAP in PHP

LITTLE DISAPPOINTMENTSThings That ext/soap Does Not Support...

Page 94: The State of SOAP in PHP

DateTime objects

Page 95: The State of SOAP in PHP

but you can use type maps until there is support!\o/

Page 96: The State of SOAP in PHP

XSD:DATETIME TYPE MAP

function to_datetime_xml(DateTime $dateTime) {  return '<dateTime>'.$dateTime‐>format('Y‐m‐d\TH:i:sP').'</dateTime>';}

function from_datetime_xml($xmlFragmentString) {  return new DateTime(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' => 'dateTime',      'to_xml' => 'to_datetime_xml',      'from_xml' => 'from_datetime_xml',    ),  ),));

Page 97: The State of SOAP in PHP

DOCUMENT/LITERAL WRAPPED

• Document style services yield messages that can 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

Page 98: The State of SOAP in PHP

DOS AND DON’TSKeep This in Mind

Page 99: The State of SOAP in PHP

enable the SOAP_SINGLE_ELEMENT_ARRAYS feature

Page 100: The State of SOAP in PHP

don’t use SoapServer::fault()

Page 101: The State of SOAP in PHP

use the exceptions option

Page 102: The State of SOAP in PHP

double-check soap_use_error_handler()

Page 103: The State of SOAP in PHP

don’t use cookies or other forms of state, ever

Page 104: The State of SOAP in PHP

FRAMEWORK HIGHLIGHTSZend Framework & Agavi

Page 105: The State of SOAP in PHP

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 auto WSDL generation

Page 106: The State of SOAP in PHP

Zend_Soap_Autodiscover generates WSDLs for you!

Page 107: The State of SOAP in PHP

using PHPDoc comments

Page 108: The State of SOAP in PHP

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(); // only dumps a WSDL, does not start a server!

Page 109: The State of SOAP in PHP

also very nice for prototyping

Page 110: The State of SOAP in PHP

but might get difficult with complex stuff

Page 111: The State of SOAP in PHP

e.g. multi-dimensional arrays, can’t do those in PHPDoc

Page 112: The State of SOAP in PHP

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

Page 113: The State of SOAP in PHP

Demo

Page 114: The State of SOAP in PHP

SOAP VERSUS RESTYour Thoughts Please

Page 115: The State of SOAP in PHP

!e End

Page 116: The State of SOAP in PHP

Questions?

Page 117: The State of SOAP in PHP

THANK YOU!This was

http://joind.in/1243by

@dzuelke