Slide 1

Slide 1 text

Sweet  Mother of  SOAP

Slide 2

Slide 2 text

• Chemical  composition • Household  used • Soap  making  process • Bathing  for  dummies Table  of  contents

Slide 3

Slide 3 text

Remember  SOAP?

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Simple  HTTP Documentation  – if  lucky Various  data  formats Faster Easier Standardized Protocol Service description XML Slower More complex

Slide 6

Slide 6 text

Simple  HTTP Documentation  – if  lucky Various  data  formats Faster Easier Standardized Protocol Service description XML Slower More complex

Slide 7

Slide 7 text

Simple  HTTP Documentation  – if  lucky Various  data  formats Faster Easier Standardized Protocol Service description XML Slower More complex

Slide 8

Slide 8 text

Simple  HTTP Documentation  – if  lucky Various  data  formats Faster Easier Standardized Protocol Service description XML Slower More complex

Slide 9

Slide 9 text

Simple  HTTP Documentation  – if  lucky Various  data  formats Faster Easier Standardized Protocol Service description XML Slower More complex

Slide 10

Slide 10 text

S imple O bject A ccess P rotocol

Slide 11

Slide 11 text

XML  EVERYWHERE!

Slide 12

Slide 12 text

WSDL  Service  Description

Slide 13

Slide 13 text

WSDL  Service  Description

Slide 14

Slide 14 text

Messaging

Slide 15

Slide 15 text

What  is  your  worst SOAP  experience?

Slide 16

Slide 16 text

SOME  RANDOM  SQL  CONDITIONS WITHOUT  KNOWING  THE  DB  SCHEMA

Slide 17

Slide 17 text

<data> PHNvbWUgaHRtb*snap*D0iIiAvPg== </data>

Slide 18

Slide 18 text

5  levels  deep XML  object XML string SOAP response

Slide 19

Slide 19 text

S imple O bject A ccess P rotocol

Slide 20

Slide 20 text

Why  do  people  hate  SOAP?

Slide 21

Slide 21 text

XML  EVERYWHERE!

Slide 22

Slide 22 text

W5p2EqlPUbH+mJmT7hUf+0tykXw= t2+F8XtvNTNpDEtHJknhDrJBFKqRCHEzmEHC6kcogKTxfOAmjDSb3IJKqal4aDdN6QcY66rjMV1uVAOXhE6nyxcI/YLr0qzj7O33HILVpFhx READING  SOAP  ISN'T  FUN

Slide 23

Slide 23 text

Service  descriptions

Slide 24

Slide 24 text

Platform  Incompatibilities

Slide 25

Slide 25 text

EXT-­‐SOAP EXT-­‐SOAP

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

$client  = new  SoapClient('some.wsdl'); $client-­‐>SomeFunction($a,  $b,  $c);

Slide 28

Slide 28 text

$client  =  new  SoapClient('some.wsdl'); $client-­‐>SomeFunction(''); $client-­‐>SomeFunction(['someInfo'  => true]); $client-­‐>SomeFunction(new  stdClass()); $client-­‐>SomeFunction(new  SoapParam()); $client-­‐>SomeFunction(new  SoapVar()); $client-­‐>SomeFunction(new  MyType());   //  ...

Slide 29

Slide 29 text

$client-­‐>__getFunctions(); 'array(26)  {  [0]=>  string(70)  "ProductInfo KeywordSearchRequest(KeywordRequest $KeywordSearchRequest)"  [1]=>  string(79)  "ProductInfo TextStreamSearchRequest(TextStreamRequest $TextStreamSearchRequest)"  [2]=>  string(64)   "ProductInfo PowerSearchRequest(PowerRequest $PowerSearchRequest)"  ...  [23]=>   string(107)  "ShoppingCart RemoveShoppingCartItemsRequest(RemoveShoppingCartItemsRequest $RemoveShoppingCartItemsRequest)"  [24]=>  string(107)  "ShoppingCart ModifyShoppingCartItemsRequest(ModifyShoppingCartItemsRequest $ModifyShoppingCartItemsRequest)"  [25]=>  string(118)  "GetTransactionDetailsResponse GetTransactionDetailsRequest(GetTransactionDetailsRequest $GetTransactionDetailsRequest)"   }';

Slide 30

Slide 30 text

$client-­‐>__getTypes(); 'array(88)  {  [0]=>  string(30)  "ProductLine ProductLineArray[]"  [1]=>  string(85)  "struct ProductLine {  string   Mode;  string  RelevanceRank;  ProductInfo ProductInfo;  }"  [2]=>  string(105)  "struct ProductInfo {  string   TotalResults;  string  TotalPages;  string  ListName;  DetailsArray Details;  }"  ...  [85]=>  string(32)   "ShortSummary ShortSummaryArray[]"  [86]=>  string(121)  "struct GetTransactionDetailsRequest {  string   tag;  string  devtag;  string  key;  OrderIdArray OrderIds;  string  locale;  }"  [87]=>  string(75)  "struct GetTransactionDetailsResponse {  ShortSummaryArray ShortSummaries;  }"  }';

Slide 31

Slide 31 text

No  extensions  allowed!

Slide 32

Slide 32 text

class  MySoapClient extends  SoapClient { public  function  __doRequest( $request, $location, $action, $version, $one_way =  0 ) { //  your  logic  here   } }

Slide 33

Slide 33 text

Crappy  error  handling

Slide 34

Slide 34 text

Basic  Auth on  WSDL HTTP  Chunked  transfer  encoding NTLM  Authentication Common  extensions  like  WSA and  WSSE

Slide 35

Slide 35 text

Crappy  API • __call() • __doRequest()

Slide 36

Slide 36 text

Dealing  with  SOAP Like  a  SIR!

Slide 37

Slide 37 text

Value  Objects class  Request implements  RequestInterface {} class  Response implements  ResponseInterface {} class  MyType {}

Slide 38

Slide 38 text

Classmap class  MyClientClassMap { public  static  function  getCollection():  ClassMapCollection { return  new  ClassMapCollection([ new  ClassMap('GetWeatherRequest',  Type\GetWeatherRequest::class), new  ClassMap('GetWeatherResponse',  Type\GetWeatherResponse::class), ]); } }

Slide 39

Slide 39 text

Value  objects  generation $  ./bin/soap-­‐client  generate:types $  ./bin/soap-­‐client  generate:classmap

Slide 40

Slide 40 text

Type  converters class  DateTypeConverter implements  TypeConverterInterface { const NAMESPACE  = 'http://www.w3.org/2001/XMLSchema'; const TYPE  = 'date'; public  function  convertXmlToPhp(string  $data) { $doc  = new  DOMDocument(); $doc-­‐>loadXML($data); return  new  DateTime($doc-­‐>textContent); } public  function  convertPhpToXml(DateTime $value):  string { return  sprintf('<%1$s>%2$s',  self::TYPE,  $value-­‐>format('Y-­‐m-­‐d')); } }

Slide 41

Slide 41 text

Client  API class  YourClient { private  $soapClient; function  getWeather(WeatherRequest $request)  :  WeatherResponse { return  $this-­‐>soapClient-­‐>getWeather($request); } }

Slide 42

Slide 42 text

Client  generation  tools $  ./bin/soap-­‐client  generate:config $  ./bin/soap-­‐client  generate:clientfactory $  ./bin/soap-­‐client  generate:client

Slide 43

Slide 43 text

Event  based  client class  YourClient {       function  call(string $method,  RequestInterface $request):  ResponseInterface { $this-­‐>dispatcher-­‐>dispatch('soap.request',  []); try  { $response  = $this-­‐>soapClient-­‐>{$method}($request); }  catch  (\Exception  $exception)  { $this-­‐>dispatcher-­‐>dispatch('soap.fault',  []); throw  $exception; } $this-­‐>dispatcher-­‐>dispatch('soap.response',  []); return  $response; } }

Slide 44

Slide 44 text

Event  Listeners class  Logger implements  EventSubscriber {} class  RequestValidator implements  EventSubscriber {} class  Cacher implements  EventSubscriber {}

Slide 45

Slide 45 text

HTTP  SoapClient (PSR-­‐7) class  CustomSoapClient extends  SoapClient { private  $handler; public  function  __doRequest($request,  $location,  $action,  $version,  $oneWay = 0) { return  $this-­‐>handler-­‐>request($request,  $location,  $action,  $version,  $oneWay); }         }

Slide 46

Slide 46 text

HTTP  Middleware  (PSR-­‐15) class  BasicAuth implements  MiddlewareInterface {} class  NtlmAuth implements  MiddlewareInterface {} class  HttpLogger implements  MiddlewareInterface {} class  HttpCacher implements  MiddlewareInterface {}

Slide 47

Slide 47 text

SOAP  Extension  Middleware  (PSR-­‐15) class  Wsa implements  MiddlewareInterface {} class  Wsse implements  MiddlewareInterface {} class  SwaAttachments implements  MiddlewareInterface {} class  MTOMAttachments implements  MiddlewareInterface {}

Slide 48

Slide 48 text

Ext-­‐soap  bufixing Middleware  (PSR-­‐15) class  DisableWsdlExtensions implements  MiddlewareInterface {} class  RenameXsdType implements  MiddlewareInterface {} class  RemoveEmptyNode implements  MiddlewareInterface {} class  AddSoapHeader implements  MiddlewareInterface {}

Slide 49

Slide 49 text

Client  configuration $builder  = new  ClientBuilder( new  ClientFactory(MyCustomClient::class), 'webservice.wsdl', ['cache_wsdl'  => $shouldCacheWsdl] ); $builder-­‐>addClassMap(new  MyCustomClientClassmap()); $builder-­‐>withHandler(new  GuzzleHandler()) ; $builder-­‐>addMiddleware(new  MyMiddleware()); $client  = $builder-­‐>getClient();

Slide 50

Slide 50 text

Testing testGetWheater() testGetWheater()

Slide 51

Slide 51 text

Testing /** *  @test *  @vcr soap-­‐get-­‐city-­‐weather-­‐by-­‐zip-­‐10013.yml */ function  it_should_be_possible_to_hook_php_vcr_for_testing() { $result  = $this-­‐>soapClient-­‐>GetCityWeatherByZIP(['ZIP'  => '10013']); $this-­‐>assertTrue($result-­‐>GetCityWeatherByZIPResult-­‐>Success); }

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

phpro /  soap-­‐client

Slide 54

Slide 54 text

Toon  out  !  !  !