Building web services with Zend Framework King Foo Jonas Mariën 13 July 2010, Vlissingen NL
This talk = beta remarks and suggestions are welcome
King Foo Launched January 2010
5 experienced PHP developers (4 Zend Certified Engineers, MySQL, Linux, scaling, and architecture experience
LAMP, but wandering off into different grounds at regular intervals Having fun with mobile stuff and web services for example ...
This talk Not about talking to Flickr or Google
About others talking to us So we're going to create web services: Using Zend Framework
For others to consume
Question time Heard about / tried Zend Framework?
Zend Framework Components, high quality
Sufficient documentation
MVC if you want
Nice server components
Zend Framework Download, unpack wget http://framework.zend.com/releases/ZendFramework-1.10.6/ZendFramework-1.10.6.tar.gz tar zxvf ZendFramework-1.10.6.tar.gz cp -ar ZendFramework-1.10.6/library . cp -ar ZendFramework-1.10.6/bin . alias zf=bin/zf.sh Create project, module, create controller with views zf create project . zf create module admin zf create controller index index-action-included=1 admin
Zend Framework You need one more thing to enable modules: resources.frontController.moduleDirectory = APPLICATION_PATH "/modules" resources.modules[] = Plus, we want our own libraries, eventually: autoloaderNamespaces.kingfoo = "Kingfoo_"
Zend Framework . |-- application | |-- Bootstrap.php | |-- configs | | `-- application.ini | |-- controllers | | |-- ErrorController.php | | `-- IndexController.php | |-- models | |-- modules | | `-- admin | `-- views | |-- helpers | `-- scripts |-- bin |-- docs | `-- README.txt |-- library | `-- Zend | |-- Acl | |-- Acl.php | .... | |-- Wildfire | `-- XmlRpc |-- public | `-- index.php |-- tests | |-- application | | |-- bootstrap.php | | `-- controllers | |-- library | | `-- bootstrap.php | `-- phpunit.xml . `-- admin |-- controllers | `-- IndexController.php |-- models `-- views |-- filters |-- helpers `-- scripts . |-- application | |-- Bootstrap.php | |-- configs | | `-- application.ini | |-- controllers | | |-- ErrorController.php | | `-- IndexController.php | |-- models | |-- modules | | `-- admin | `-- views | |-- helpers | `-- scripts |-- bin |-- docs | `-- README.txt |-- library | `-- Zend | |-- Acl | |-- Acl.php | .... | |-- Wildfire | `-- XmlRpc |-- public | `-- index.php |-- tests | |-- application | | |-- bootstrap.php | | `-- controllers | |-- library | | `-- bootstrap.php | `-- phpunit.xml
Zend Framework Create Apache vhost
Add to /etc/hosts
Reload Apache
Question time Heard about / tried web services?
Web services From Wikipedia: Web services are typically application programming interfaces (API) or web APIs that are accessed via Hypertext Transfer Protocol (HTTP) and executed on a remote system hosting the requested services. Web services tend to fall into one of two camps: Big Web Services and RESTful Web Services.
Different kinds of WS SOAP
XML-RPC
JSON-RPC
REST BTW, I don't want to talk about Zend_Amf
Exposing something class Kingfoo_Quote { public function __construct() { $array[0] = 'Chuck Norris counted to infinity - twice.'; $array[9] = 'Chuck Norris doesn’t wash his clothes, he disembowels them.'; $this->_quotes = $array; } /** * returns entire liste of quotes * @return array */ public function getList() { return $this->_quotes; } .... /** * returns a random single quote * @return string */ public function randomQuote() { $arr = $this->_quotes; shuffle($arr); return $arr[0]; } }
SOAP Simple Object Access Protocol (now just SOAP)
Big spec, even bigger with WS-*
RPC style, method oriented
Server and WSDL
SOAP 1.1 and SOAP 1.2 SOAP 1.2 allows non-HTTP too
SOAP governed by a W3C working group
SOAP with ZF SOAP with plain PHP works, but can be cumbersome
The real power: WSDL generation and reflection being used for discovery
Strategies for discovering more complex messages and responses are available
Docblock comments are very important here
SOAP with ZF if (isset($_GET['WSDL'])) { $autodiscover = new Zend_Soap_AutoDiscover(); $autodiscover->setClass('Kingfoo_Quote'); $autodiscover->setUri('http://presentation-zfws/SOAP.php'); $autodiscover->handle(); } else { $options = array('soap_version' => SOAP_1_2); $server = new Zend_Soap_Server('http://presentation- zfws/SOAP.php?WSDL=1', $options); $server->setObject(new Kingfoo_Quote()); $server->handle(); }

Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vlissingen)

  • 1.
    Building web services with Zend Framework King Foo Jonas Mariën 13 July 2010, Vlissingen NL
  • 2.
    This talk =beta remarks and suggestions are welcome
  • 3.
    King Foo LaunchedJanuary 2010
  • 4.
    5 experienced PHPdevelopers (4 Zend Certified Engineers, MySQL, Linux, scaling, and architecture experience
  • 5.
    LAMP, but wanderingoff into different grounds at regular intervals Having fun with mobile stuff and web services for example ...
  • 6.
    This talk Notabout talking to Flickr or Google
  • 7.
    About others talkingto us So we're going to create web services: Using Zend Framework
  • 8.
  • 9.
    Question time Heardabout / tried Zend Framework?
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
    Zend Framework Download,unpack wget http://framework.zend.com/releases/ZendFramework-1.10.6/ZendFramework-1.10.6.tar.gz tar zxvf ZendFramework-1.10.6.tar.gz cp -ar ZendFramework-1.10.6/library . cp -ar ZendFramework-1.10.6/bin . alias zf=bin/zf.sh Create project, module, create controller with views zf create project . zf create module admin zf create controller index index-action-included=1 admin
  • 15.
    Zend Framework Youneed one more thing to enable modules: resources.frontController.moduleDirectory = APPLICATION_PATH "/modules" resources.modules[] = Plus, we want our own libraries, eventually: autoloaderNamespaces.kingfoo = "Kingfoo_"
  • 16.
    Zend Framework .|-- application | |-- Bootstrap.php | |-- configs | | `-- application.ini | |-- controllers | | |-- ErrorController.php | | `-- IndexController.php | |-- models | |-- modules | | `-- admin | `-- views | |-- helpers | `-- scripts |-- bin |-- docs | `-- README.txt |-- library | `-- Zend | |-- Acl | |-- Acl.php | .... | |-- Wildfire | `-- XmlRpc |-- public | `-- index.php |-- tests | |-- application | | |-- bootstrap.php | | `-- controllers | |-- library | | `-- bootstrap.php | `-- phpunit.xml . `-- admin |-- controllers | `-- IndexController.php |-- models `-- views |-- filters |-- helpers `-- scripts . |-- application | |-- Bootstrap.php | |-- configs | | `-- application.ini | |-- controllers | | |-- ErrorController.php | | `-- IndexController.php | |-- models | |-- modules | | `-- admin | `-- views | |-- helpers | `-- scripts |-- bin |-- docs | `-- README.txt |-- library | `-- Zend | |-- Acl | |-- Acl.php | .... | |-- Wildfire | `-- XmlRpc |-- public | `-- index.php |-- tests | |-- application | | |-- bootstrap.php | | `-- controllers | |-- library | | `-- bootstrap.php | `-- phpunit.xml
  • 17.
  • 18.
  • 19.
  • 20.
    Question time Heardabout / tried web services?
  • 21.
    Web services FromWikipedia: Web services are typically application programming interfaces (API) or web APIs that are accessed via Hypertext Transfer Protocol (HTTP) and executed on a remote system hosting the requested services. Web services tend to fall into one of two camps: Big Web Services and RESTful Web Services.
  • 22.
  • 23.
  • 24.
  • 25.
    REST BTW, Idon't want to talk about Zend_Amf
  • 26.
    Exposing something classKingfoo_Quote { public function __construct() { $array[0] = 'Chuck Norris counted to infinity - twice.'; $array[9] = 'Chuck Norris doesn’t wash his clothes, he disembowels them.'; $this->_quotes = $array; } /** * returns entire liste of quotes * @return array */ public function getList() { return $this->_quotes; } .... /** * returns a random single quote * @return string */ public function randomQuote() { $arr = $this->_quotes; shuffle($arr); return $arr[0]; } }
  • 27.
    SOAP Simple ObjectAccess Protocol (now just SOAP)
  • 28.
    Big spec, evenbigger with WS-*
  • 29.
  • 30.
  • 31.
    SOAP 1.1 andSOAP 1.2 SOAP 1.2 allows non-HTTP too
  • 32.
    SOAP governed bya W3C working group
  • 33.
    SOAP with ZFSOAP with plain PHP works, but can be cumbersome
  • 34.
    The real power:WSDL generation and reflection being used for discovery
  • 35.
    Strategies for discoveringmore complex messages and responses are available
  • 36.
    Docblock comments arevery important here
  • 37.
    SOAP with ZFif (isset($_GET['WSDL'])) { $autodiscover = new Zend_Soap_AutoDiscover(); $autodiscover->setClass('Kingfoo_Quote'); $autodiscover->setUri('http://presentation-zfws/SOAP.php'); $autodiscover->handle(); } else { $options = array('soap_version' => SOAP_1_2); $server = new Zend_Soap_Server('http://presentation- zfws/SOAP.php?WSDL=1', $options); $server->setObject(new Kingfoo_Quote()); $server->handle(); }
  • 38.
    SOAP with ZFRequest
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
    Limited set ofdatatypes, nothing like WSDL
  • 44.
    Spec: The requestbody is wrapped in a single methodCall tag
  • 45.
    That container shouldcontain a single methodName tag
  • 46.
    The method nameshould be a string only containin a-z,A-Z,0-9 and any of these characters: _ . : /
  • 47.
    It is upto the server how to interprete this methodName
  • 48.
    Parameters for themethodName being called are contained in a params tag
  • 49.
    Inside the paramstag, one or more param tags are listed
  • 50.
    Each param taglooks like this: <param><value>...</value></param>
  • 51.
    XML-RPC REQUEST: <?xmlversion=&quot;1.0&quot;?> <methodCall> <methodName>zfwsdemo.getQuote</methodName> <params> <param> <value><int>2</int></value> </param> </params> </methodCall> </code> RESPONSE <code> <?xml version=&quot;1.0&quot;?> <methodResponse> <params> <param> <value>... Chuck Norris ...</value> </param> </params> </methodResponse> </code>
  • 52.
    XML-RPC More complexvalues: Array
  • 53.
  • 54.
    system.* (listMethods, methodSignature,methodHelp, multicall ...)
  • 55.
    XML-RPC with ZFSERVER $server = new Zend_XmlRpc_Server(); $server->setClass('Kingfoo_Quote','zfwsdemo'); echo $server->handle(); CLIENT $client = new Zend_XmlRpc_Client('http://presentation-zfws/XMLRPC.php'); //get list of methods $result = $client->call('system.listMethods'); //get a random quote $result = $client->call('zfwsdemo.randomQuote');
  • 56.
  • 57.
    TCP/IP sockets areallowed too (not only HTTP)
  • 58.
    Request, response, errorobject, batches
  • 59.
    Client and serverare peers, sending each other notifications
  • 60.
    Two versions: 1.0and 2.0 (ZF supports both) Support for batches
  • 61.
  • 62.
    JSON-RPC with ZFSERVER $server = new Zend_Json_Server(); $server->setClass('Kingfoo_Quote'); $server->handle(); CLIENT $request = new stdClass(); $request->jsonrpc = '2.0'; $request->method = 'getQuote'; $request->params = array(1); $request->id = time(); $json = Zend_Json::encode($request); $client = new Zend_Http_Client('http://presentation-zfws/JSONRPC.php'); $response = $client->setRawData($json, 'application/json')->request('POST');
  • 63.
    JSON-RPC with ZFAND NOW WITH SMD $server = new Zend_Json_Server(); $server->setClass('Kingfoo_Quote'); if ('GET' == $_SERVER['REQUEST_METHOD']) { $server->setTarget('/JSONRPC.php') ->setEnvelope(Zend_Json_Server_Smd::ENV_JSONRPC_2); $smd = $server->getServiceMap(); header('Content-Type: application/json'); echo $smd; return; } $server->handle();
  • 64.
    JSON-RPC with ZFJSON-RPC very interesting with for example the jQery Zend JSON-RPC plugin (http://plugins.jquery.com/project/zendjsonrpc) proxy = jQuery.Zend.jsonrpc({url: '/JSONRPC.php'}); result = proxy.getList(); A demo ...
  • 65.
    Possible with Dojotoo, see ZF manual
  • 66.
    REST Representational StateTransfer (also ReST)
  • 67.
  • 68.
    XML, increasingly JSONas message format
  • 69.
    HTTP verbs definenature of action on resource
  • 70.
    No spec orstandard, more like a 'movement'
  • 71.
    RESTafarians leave funnycomments on blogs and have strong opinions. True SOAP believers are a dying race, it appears. Have a laugh, Google for 'The S stands for Simple'
  • 72.
    REST GET POSTPUT DELETE /quotes Get list Add quote to list Update entire list Delete entire list /quotes/<id> Get quote with id <id> Add subquote (unlikely) Update single quote Delete single quote List = oftern referred to as a 'collection'
  • 73.
    REST with ZFAt first conceived as a standalone service, much like Zend_Soap: Zend_Rest
  • 74.
    Now more andmore integrated, using Zend_Rest_Controller and Zend_Rest_Route
  • 75.
    Future versions ofZF (2.0?) will probably have it fully integrated in the controller, using context switching (see posts by Matthew Weier O'Phinney at http://weierophinney.net/matthew/)
  • 76.
    REST with ZFZend_Rest_Controller controller implementing it must implement these actions: class Rest_IndexController extends Zend_Rest_Controller { public function init() {} public function indexAction() {} public function getAction() {} public function postAction() {} public function putAction() {} public function deleteAction() {} }
  • 77.
    REST with ZFZend_Rest_Route Add module zf create module rest Add to Bootstrap
  • 78.
    protected function _initRestroutes(){ $this->bootstrap('frontController'); $frontController = Zend_Controller_Front::getInstance(); $router = $frontController->getRouter(); $restRoute = new Zend_Rest_Route($frontController,array(),array('rest')); $router->addRoute('rest', $restRoute); }
  • 79.
    REST with ZFZend_Rest_Route detects HTTP verbs like POST and points them to a predefined list of corresponding URI end points. Our example code will result in behaviour like this: URI Module_Controller action GET /rest/quote/ Rest_QuoteController indexAction() GET /rest/quote/:id Rest_QuoteController getAction() POST /rest/quote Rest_QuoteController postAction() PUT /rest/quote/:id Rest_QuoteController putAction() DELETE /rest/quote/:id Rest_QuoteController deleteAction() These additional end points are supported too, as a workaround for environments where PUT or DELETE are blocked by a firewall for example: URI Module_Controller action POST /rest/quote/:id?_method=PUT Rest_QuoteController putAction() POST /rest/quote/:id?_method=DELETE Rest_QuoteController deleteAction() And that counts for every controller in the module named 'rest', as they are all considered RESTful.
  • 80.
    REST with ZFSERVER -> code example: route + controller CLIENT Zend_Rest_Client -> no $client = new Zend_Http_Client('http://presentation-zfws/rest/index/2'); $response = $client->request(); echo $response->getBody();
  • 81.
    REST – Responsecodes Error and response codes ! For example: 200 OK Everything allright 201 Created The object or resources is created 204 Empty body Resource is deleted 400 Bad Request Request is not understood or was malformed. Explanation may be available in the body . 401 Forbidden Permission denied. / credentials invalid 404 Not Found Resource could not be found. 409 Conflict/Duplicate Resource already exists 405 Method Not Allowed The action (POST, PUT, ...) is not allowed on the resource 410 Gone Resource does not/no longer exist 500 Internal server error Something went wrong on the server side 501 Not Implemented The action is not available.
  • 82.
    REWIND We hadan overview of different kinds of webservices that you can create using ZF
  • 83.
    RPC vs Resourceoriented solutions
  • 84.
    What do youchoose? Depends on your requirements
  • 85.
    Extras How canwe restrict access to our service?
  • 86.
  • 87.
  • 88.
    Extending the existingZF classes and making things even more easy for yourself
  • 89.
    Thanks for yourtime Questions? Want us to work for you? [email_address] www.king-foo.be @jonasmarien