You are on page 1of 55

PHP and Web Services: Perfect Partners

About Me

Lorna Jane Mitchell PHP Developer/Trainer/Consultant at Ibuildings

Hosting DPC Editor at techPortal

http://lornajane.net @lornajane

PHP

PHP: "solving the web problem" The problem evolves PHP evolves

PHP

Server Client Web application tool Command line tool GTK ...

PHP

Ubiquitous Runs on your platform

*nix mac windows (yes really, rather well!)

Can talk to your other systems

Web Services

"scalable, reusable libraries" Interface over HTTP Modular application design

Architecture

Traditional Architecture

Traditional Architecture

Additional Channels

Services Architecture

Inside The Service Layer

Data Formats

JSON

JavaScript Object Notation Natively read/write in most languages Very simple! (we like simple) Limitations

no data typing no distinction between object and array

Writing JSON from PHP


1 2 3 4 5 6 7 8 9 10 11 <?php $menu['starter'] = array( "prawn cocktail", "soup of the day"); $menu['main course'] = array( "roast chicken", "fish 'n' chips", "macaroni cheese"); $menu['pudding'] = array( "cheesecake", "treacle sponge"); echo json_encode($menu);

{"starter":["prawncocktail","soupoftheday"],"main course":["roastchicken","fish'n'chips","macaroni cheese"],"pudding":["cheesecake","treaclesponge"]}

Reading JSON from PHP


1 <?php 2 3 $json = '{"starter":["prawn cocktail","soup of the day"],"main course":["roast chicken","fish \'n\' chips","macaroni cheese"],"pudding":["cheesecake","treacle sponge"]}'; 4 5 print_r(json_decode($json));

Reading JSON from PHP


stdClass Object ( [starter] => Array ( [0] => prawn cocktail [1] => soup of the day ) [main course] => Array ( [0] => roast chicken [1] => fish 'n' chips [2] => macaroni cheese ) [pudding] => Array ( [0] => cheesecake [1] => treacle sponge ) )

XML

eXtensible Markup Language Familiar Can give more detail than JSON Native read/write in most languages

Working with XML from PHP

Lots of options SimpleXML DOM

SimpleXML Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php $xml = <<< XML <?xml version="1.0" ?> <menus> <menu>Lunch</menu> <menu>Dinner</menu> <menu>Dessert</menu> <menu>Drinks</menu> </menus> XML; $simplexml = new SimpleXMLElement($xml); var_dump($simplexml);

SimpleXML Example
object(SimpleXMLElement)#1 (1) { ["menu"]=> array(5) { [0]=> string(5) "Lunch" [1]=> string(6) "Dinner" [2]=> string(7) "Dessert" [3]=> string(6) "Drinks" } }

SimpleXML Example
1 <?php 2 3 $simplexml = simplexml_load_string('<?xml version="1.0" ?><menus/>'); 4 $simplexml->addChild('menu','Lunch'); 5 $simplexml->addChild('menu','Dinner'); 6 $simplexml->addChild('menu','Drinks'); 7 $simplexml->addChild('menu','Dessert'); 8 9 echo $simplexml->asXML();

SimpleXML Example
<?xml version="1.0"?> <menus> <menu>Lunch</menu> <menu>Dinner</menu> <menu>Dessert</menu> <menu>Drinks</menu> </menus>

Service Types

Service Types

*-RPC
XML-RPC JSON-RPC

SOAP REST

RPC

All URLs point to a single endpoint Parameters give method names Request body can take a variety of formats

Example RPC services

Using Flickr's XML-RPC Test method: just echoes back to user XML formatted data

Flickr Echo Example: XML


<?xml version="1.0"?> <methodCall> <methodName>flickr.test.echo</methodName> <params> <param> <value> <struct> <member> <name>api_key</name> <value>....</value> </member> </struct> </value> </param> </params> </methodCall>

RPC from PHP: curl


1 2 3 4 5 6 7 8 9 10 11 <?php // $xml is existing SimpleXMLElement Object $url = 'http://api.flickr.com/services/xmlrpc/'; $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml->asXML()); $response = curl_exec($ch); curl_close($ch);

RPC from PHP: pecl_http


1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php $url = 'http://api.flickr.com/services/xmlrpc/'; // procedural method $response = http_post_data($url, $xml->asXML()); // alternative method $request = new HTTPRequest($url, HTTP_METH_POST); $request->setRawPostData($xml->asXML()); $request->send(); $response = $request->getResponseBody(); var_dump($response);

Flickr Response
<?xml version="1.0" encoding="utf-8" ?> <methodResponse> <params> <param> <value> <string>&lt;api_key&gt;54rt346&lt;/api_key&gt; </string> </value> </param> </params> </methodResponse>

RPC Advantages

RPC is a great format for wrapping existing functionality Can abstract between existing systems Familiar functional paradigm

Delivering RPC

Consumers will need


Service URL Docs of functions and arguments If this was an existing system, existing docs may suffice

Wrapping RPC

RPC is a library-like interface Can easily wrap existing libraries to call like this Can wrap an interface to an RPC service to look like a library

Wrapping RPC Example


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php class Handler { function __call($method, $args) { $ch = curl_init('http://localhost'); $data['method'] = $method; foreach($args as $a) $data[$a] = $a; curl_setopt($ch, CURLOPT_POST,1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); $response = curl_exec($ch); curl_close($ch); } } $h = new Handler(); $h->dance('cat','dog','rabbit','penguin'); var_dump($response);

SOAP

Special case of RPC using XML Has given formats for messages and errors Libraries exist for creating server and client in most languages

PHP SOAP Server Example


require_once('lib/myClass.php'); $server = new SoapServer("service.wsdl"); $server->setClass("MyClass"); $server->handle();

PHP SOAP Client Example


$wsdl = "Service.wsdl"; $client = new SoapClient($wsdl, $params); $output = $client->requestShot( 'http://www.php.net','', 300, 400);

WSDL

Web Service Description Language Widely used with SOAP Describes the methods, arguments and data types available IDEs can read this and hint Validity of requests is checked before they are sent

WSDL
<?xml version ='1.0' encoding ='UTF-8' ?> <definitions name='MyClass' http://schemas.xmlsoap.org/soap/encoding/' targetNamespace='urn:MyClassInventory' <message name='getAccountStatusRequest'> </message> <part name='accountID' type='xsd:string'/> xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/' xmlns:tns='urn:MyClassInventory' xmlns='http://schemas.xmlsoap.org/wsdl/'> xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soapenc=' <message name='getAccountStatusResponse'> <part name='accountID' type='xsd:string'/> <part name='counter' type='xsd:float' />

</message>

<portType name='MyClassPortType'>

<operation name='getAccountStatus'>

<input message='tns:getAccountStatusRequest'/>

</operation> </portType>

<output message='tns:getAccountStatusResponse'/>

<binding name='MyClassBinding' type='tns:MyClassPortType'> <soap:binding style='rpc' transport='http://schemas.xmlsoap.org/soap/http'/> <soap:operation soapAction='urn:xmethods-delayed-quotes#getAccountStatus'/> <input> <soap:body use='encoded' namespace='urn:xmethods-delayed-quotes' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>

<operation name='getAccountStatus'>

</input>

<output>

<soap:body use='encoded' namespace='urn:xmethods-delayed-quotes' encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>

</binding>

</operation>

</output>

<service name='MyClassService'>

<port name='MyClassPort' binding='tns:MyClassBinding'> </port>

<soap:address location='http://rivendell.local:10002/MyClassServiceServer.php'/>

</service>

</definitions>

Delivering SOAP

In WSDL mode, only the WSDL needs to be supplied Otherwise method names, arguments and types will be needed

REST

A series of concepts Generally uses HTTP (HyperText Transfer Protocol) URLs are resource locations Verbs tell the service what to do Status codes indicate what the outcome was

Implementing REST

Standard application architecture Routing to map requests to internal functionality Output not always HTML

REST CRUD
Action Retrieve Create Update Delete HTTP Verb GET POST PUT DELETE

REST Examples

GET

http://localhost/users http://localhost/users/harry

POST

http://localhost/users

PUT

http://localhost/users/harry

REST from PHP: GET


1 <?php 2 3 $result = file_get_contents('http://localhost/users'); 4 var_dump($result);

REST from PHP: GET


1 <?php 2 3 $ch = curl_init('http://localhost/users'); 4 5 curl_exec($ch);

Health Warning!

curl will echo output use CURLOPT_RETURNTRANSFER to capture it instead

REST from PHP: POST


1 2 3 4 5 6 7 8 9 10 11 <?php $ch = curl_init('http://localhost/users'); $data = array ("name" => "Cho Chang", "house" => "Ravenclaw"); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_exec($ch);

REST from PHP: PUT


1 2 3 4 5 6 7 8 9 10 11 12 13 <?php $ch = curl_init('http://localhost/users/cho'); $data = array ("name" => "Cho Chang", "house" => "Ravenclaw" "age" => 15); curl_setopt($handle, CURLOPT_CUSTOMREQUEST, 'PUT'); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_exec($ch);

REST from PHP: DELETE


1 2 3 4 5 6 7 <?php $ch = curl_init('http://localhost/users/ginny'); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); curl_exec($ch);

Delivering REST

Full documentation including URL formats, data types, and response formats Must include information about error handling

REST as an inspiration

RESTful is a strict definition REST is full of great ideas REST is great for clean, simple, robust services Cherry-pick the bits that work

Just don't call it "RESTful" :)

Resources

RESTful Web Services Leonard Richardson and Sam Ruby http://php.net http://benramsey.com http://lornajane.net

Questions ???

Thankyou

Lorna Jane Mitchell http://ibuildings.com http://lornajane.net @lornajane

http://slideshare.net/lornajane

You might also like