• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
RESTful modules in zf2
 

RESTful modules in zf2

on

  • 7,573 views

Just a simple introduction to RESTful modules in ZF2

Just a simple introduction to RESTful modules in ZF2

Statistics

Views

Total Views
7,573
Views on SlideShare
7,494
Embed Views
79

Actions

Likes
5
Downloads
93
Comments
0

5 Embeds 79

http://tweetedtimes.com 39
http://lanyrd.com 28
https://twitter.com 8
http://www.linkedin.com 3
http://www.docseek.net 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

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
  • Ringrazione l’organizzazione dello ZFDAY, gli sponsor e tutte le persone presenti.
  • Abbiamo solo 30 minuti quindi fare un veloce escursus sui service RESTful e vedremo come realizzare due moduli ZF2.Un primo molto semplice, ispirato a Zend_Rest_Server di ZF1 Un secondo utilizzando un componente integrato nella libreria ZF2
  • Il termite REST è stato coniato nel 2000 da Roy Fielding, uno degli autori del protocollo HTTP, per descrivere un sistema che permette di descrivere ed identificare le risorse web.

RESTful modules in zf2 RESTful modules in zf2 Presentation Transcript

  • RESTful Modules in ZF2Walter Dal Mut – walter.dalmut@gmail.com - @walterdalmut https://github.com/wdalmut @walterdalmut - www.corley.it - www.upcloo.com
  • About Me • Walter Dal Mut (@walterdalmut) • Electronic Engineer • Polytechnic University of Turin • Startupper • Corley S.r.l. – www.corley.it • Cloud Computing Services • UpCloo Ltd. – www.upcloo.com • Semantic Most Related Links service @walterdalmut - www.corley.it - www.upcloo.com
  • Summary• REST introduction• REST constraints• Types of RESTful services• ZF2 RESTful modules • RESTful ZF2 URI tunneling module • RESTful ZF2 CRUD module @walterdalmut - www.corley.it - www.upcloo.com
  • RESTful? What it means in few words…• Representational State Transfer (REST)• Architecture is based on Client-Server • Clients initiate requests to servers; servers process requests and return appropriate responses• Flexible, the application must know messages format • XML • JSON • Etc. @walterdalmut - www.corley.it - www.upcloo.com
  • RESTful services are resource centric• Resources (sources of specific information)• Each resource is referenced with a global identifier (URI, etc.)• Any number of connectors can mediate the request • Clients • Servers • Caches • Tunnels @walterdalmut - www.corley.it - www.upcloo.com
  • REST Constraints• Client-Server • A uniform interface separates clients from servers.• Stateless • The client–server communication is further constrained by no client context being stored on the server between requests.• Cacheable • Clients can cache responses• Layered System • Intermediary servers may improve system scalability by enabling load-balancing and by providing shared caches. They may also enforce security policies.• Uniform interface • Simplify and decouples the architecture @walterdalmut - www.corley.it - www.upcloo.com
  • Several types of RESTful services• URI Templates • http://rest.domain.tld/order/{orderID} • One of the major uses for URI templates is as human- and machine-readable documentation.• URI Tunneling • http://rest.domain.tld/PlaceOrder?pizza=margherita&type=classic • Rest.domain.tld  service • PlaceOrder method • Pizza=margherita&type=classic  arguments• POX – Plain Old XML over HTTP • Similar to URI Tunneling but information will be sent as XML document in the HTTP request from the customer. @walterdalmut - www.corley.it - www.upcloo.com
  • POX – Plain Old XML over HTTP example POST /PlaceOrder HTTP/1.1 Content-Type: application/xmlClient application Application domain <Order> <Pizza> <Name>margherita</Name> <Type>classic</Type> </Pizza> </Order> HTTP/1.1 200 OK <OrderConfirmation> <OrderID>1345</OrderID> </OrderConfirmation> @walterdalmut - www.corley.it - www.upcloo.com
  • CRUD Webservices• CRUD what it means? • Create, Read, Update and Delete • Patterns for manipulating resources across the network• Extended usage of HTTP verbs • GET • POST • PUT • DELETE• Using HTTP as an application protocol instead of a transport protocol • Web is really a big framework for building distributed systems. @walterdalmut - www.corley.it - www.upcloo.com
  • HTTP verbs in CRUD services• Get Read Operation • Used to retrive resource details • http://rest.service.tld/order/10• Post  Create Operation • Used to create new resources• Put Update Operation • Used to update existing resources• Delete Delete Operation • Used to delete existing resourcesPOST/PUT can be exchanged and sometimes PUT/DELETE can be excluded toenable javascript integration (PUT/DELETE not supported browser side[HTTP_X_HTTP_METHOD_OVERRIDE parameter]) @walterdalmut - www.corley.it - www.upcloo.com
  • CRUD SummaryVerb URI or Template UsePOST /order Create a new order, and upon success, receive a Location header specifying the new order’s URI.GET /order/{id} Request the current state of the order specified by the URI.PUT /order/{id} Update an order at the given URI with new information, providing the full representation.DELETE /order/{id} Logically remove the order identified by the given URI. @walterdalmut - www.corley.it - www.upcloo.com
  • Status code definition (short list)• 2xx (Positives) • 200 OK – The request has succeeded. • 201 Created – The server accept the request and it has created the resource. • 202 Accepted – The request has been accepted for processing, but the processing has not been completed.• 4xx (Client Errors) • 400 Bad Request – The request could not be understood by the server due to malformed syntax. • 401 Unauthorized – The request requires user authentication. • 403 Forbidden – The server understood the request, but is refusing to fulfill it. • 404 Not found – The server has not found anything matching the Request-URI. • 405 Method not allowed – The method specified in the Request-Line is not allowed for the resource identified by the Request-URI.• 5xx (Server Errors) • 500 Internal Server Error – The server encountered an unexpected condition which prevented it from fulfilling the request. • 501 Not implemented – The server does not support the functionality required to fulfill the request. • 503 Service unavailable – The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. @walterdalmut - www.corley.it - www.upcloo.com
  • RESTful module idea • Router • Wire requests to RESTful controllers • RESTful Controllersrequests Router • Uses HTTP verbs to call dedicated actions • Query models in order to serve RESTful responses Models • POST Processors Controllers • Create valid messages using formats • JSON Responses POST • XML Processor • Etc. @walterdalmut - www.corley.it - www.upcloo.com
  • Realize ZF2 tunneling RESTful module• ZF1 provides «Zend_Rest_Server» that realize URI tunneling• We can realize the same thing in 2 minutes thanks to ZF2 flexibility.• We need to configure • Router • Events• A simple example here: • https://github.com/wdalmut/ZF2-Tunneling-Restful-Module-Skeleton @walterdalmut - www.corley.it - www.upcloo.com
  • ZF2 URI Tunneling - Configuration<?phpreturn array( We have created a simple base route «/tunnel» controllers => array( invokables => array( and a dynamic rule that select a «model» and an index => TunnelingRestController, ) attached «action» ), router => array( routes => array( tunneling => array( In simple words type => ZendMvcRouterHttpSegment, options => array( • http://my-app.local/tunnel/menu/get?id=1 route => /tunnel, defaults => array( • «menu» controller => index, action => index • The model «TunnelingModelMenu» ), ), • «get» may_terminate => true, child_routes => array( • The model action «get()» default => array( type => ZendMvcRouterHttpSegment, • «id=1> options => array( route => [/:model/:action], • The action parameters «get(1)» constraints => array( controller => index, model => [a-zA-Z][a-zA-Z0-9_]*, action => [a-zA-Z][a-zA-Z0-9_]* ), ), ), ), ), ), )); @walterdalmut - www.corley.it - www.upcloo.com
  • ZF2 URI Tunneling - Controller<?phpnamespace TunnelingRest; The base «AbstractController» is very flexibleUse … and enable us to use the «dispatch» action toclass Controller extends AbstractController realize what we need in few lines.{ public function onDispatch(MvcEvent $e) { $routeMatch = $e->getRouteMatch(); In practice we allocate the model and call the $params = $routeMatch->getParams(); $vars = get_object_vars($e->getRequest()->getQuery()); requested action. The return variable is used as $filter = new ZendFilterFilterChain(); response. $filter->attach(new ZendFilterWordDashToCamelCase()); $filter->attach(new ZendFilterCallback("lcfirst")); $action = $filter->filter($params["action"]); $filter->attach(new ZendFilterCallback("ucfirst")); In case of missing model or missing action an $model = $filter->filter($params["model"]); «InvalidArgumentException» is thrown. $classname = "TunnelingModel{$model}"; if (class_exists($classname)) { $clazz = new $classname; if (property_exists($clazz, $action)) { $ret = call_user_func_array(array($clazz, $action), $vars); $e->setResult($ret); return; } else { throw new InvalidArgumentException("Method "{$action}" doesnt exists"); } } else { throw new InvalidArgumentException("Class "{$classname}" doesnt exists"); } }} @walterdalmut - www.corley.it - www.upcloo.com
  • ZF2 URI Tunneling – Model example<?phpnamespace TunnelingModel; As you can see, the «model» is a simple class definition.class Menu{ public function get($id) { • /tunnel/menu/get?id=1 return array("id" => $id); } • /tunnel/menu/add?x=pizza&y=4 public function add($name, $value) { Very simple implementation return array("name" => $name, "value" => $value); }} @walterdalmut - www.corley.it - www.upcloo.com
  • ZF2 URI Tunneling – JSON responses<?phpnamespace Tunneling; Thanks to events we can wire controller outputuse ZendMvcMvcEvent; to a post processor that converts responses inclass Module json messages.{ public function onBootstrap($e) { /** @var ZendModuleManagerModuleManager $moduleManager */ • Attach a «postProcess» action and create a $moduleManager = $e->getApplication()->getServiceManager()->get(modulemanager); /** @var ZendEventManagerSharedEventManager $sharedEvents */ json message. $sharedEvents = $moduleManager->getEventManager()->getSharedManager(); $sharedEvents->attach( ZendMvcControllerAbstractController, MvcEvent::EVENT_DISPATCH, array($this, postProcess), -100 ); }//… public function postProcess(MvcEvent $e) { $routeMatch = $e->getRouteMatch(); if (strpos($routeMatch->getMatchedRouteName(), "tunneling") !== false) { $e->getResponse()->setContent(json_encode($e->getResult()->getVariables())); return $e->getResponse(); } }} @walterdalmut - www.corley.it - www.upcloo.com
  • ZF2 RESTful CRUD modules• ZF2 provides a base controller class that can help us to realize RESTful modules in few steps • ZendMvcControllerAbstractRestfulController• CRUD based implementation (Extended) • get($id) • delete($id) • update($id) • create($id) @walterdalmut - www.corley.it - www.upcloo.com
  • ZF2 RESTful CRUD module example• Clone ZF2 Skeleton Application • Git clone https://github.com/zendframework/ZendSkeletonApplication.git my-app • Git submodule init • Git submodule update• Clone a ZF2 RESTful module • Git submodule add https://github.com/wdalmut/ZF2-Restful-Module-Skeleton.git module/Main• Add «Main» module into «configs/application.config.php»• Create you application virtual host and try it • http://my-app.local/rest/info/json [getList] • http://my-app.local/rest/info/json/1 [get] • curl –X POST –d ‘hello=world’ http://my-app.local/rest/info [create] • curl –X PUT –d ‘hello=ciao’ http://my-app.local/rest/info/1 [update] • curl –X DELETE http://my-app.local/rest/info/1 [delete] @walterdalmut - www.corley.it - www.upcloo.com
  • RESTful Controllers<?php • RESTful Controller should extends AbstractRestfulControllernamespace MainController; • 5 abstract methods (CRUD + List)use ZendMvcControllerAbstractRestfulController; • getListclass InfoController extends AbstractRestfulController{ • GET operation without parameters public function getList() { • /rest/json/info } return array(ciao => mondo); • Get public function get($id) • READ resource with parameters (ID) { • /rest/json/info/1 } • Delete public function delete($id) { • DELETE a resource } • Update public function update($id, $data) • UPDATE a resource { • Create } • CREATE a new resource public function create($data = null) { }} @walterdalmut - www.corley.it - www.upcloo.com
  • First of all play with routesrouter => array( routes => array( • Create a base route /rest that enable also formatters restful => array( type => ZendMvcRouterHttpSegment, • Formatter allow us to switch easly to JSON, options => array( route => /rest[/:formatter], XML etc. constraints => array( • Child routes play with controller and identifiers formatter => [a-zA-Z0-9_-]*, ), ), may_terminate => true, child_routes => array( default => array( type => ZendMvcRouterHttpSegment, options => array( route => [/:controller[/:id]], constraints => array( controller => [a-zA-Z][a-zA-Z0-9_-]*, id => [a-zA-Z0-9_-]* ), ), ), ), ), ), @walterdalmut - www.corley.it - www.upcloo.com
  • Formatters• RESTful services can handle different type of messages • JSON • XML • Images • Etc• The high modularity of ZF2 MVC implementation enable us to add different layers of abstractions and formatters is one of this. • Client must know what kind of messages type have to handle. • Post Processors are used to render messages @walterdalmut - www.corley.it - www.upcloo.com
  • Formatters «configs/module.config.php»errors => array( post_processor => json-pp, • The configuration allows us to define different «post processors» show_exceptions => array( message => true, • Errors can be detailed more, for example traces, messages etc. trace => true )),di => array( instance => array( alias => array( json-pp => MainPostProcessorJson, jsonp-pp => MainPostProcessorJsonp, image-pp => MainPostProcessorImage ) )), @walterdalmut - www.corley.it - www.upcloo.com
  • Wiring events (Module.php)/** * @param MvcEvent $e */ public function onBootstrap($e) • Event position -100 { /** @var ZendModuleManagerModuleManager $moduleManager */ • Handle post processors $moduleManager = $e->getApplication()->getServiceManager()->get(modulemanager); /** @var ZendEventManagerSharedEventManager $sharedEvents */ • Event position 100 $sharedEvents = $moduleManager->getEventManager()->getSharedManager(); • Handle HTTP Method Override $sharedEvents->attach( • Event position 999 ZendMvcControllerAbstractRestfulController, MvcEvent::EVENT_DISPATCH, • Handle errors array($this, postProcess), -100 ); $sharedEvents->attach( MainControllerInfoController, MvcEvent::EVENT_DISPATCH, array($e->getApplication()->getServiceManager()->get(MainHttpRestful), onDispatch), 100 ); $sharedEvents->attach( ZendMvcApplication, MvcEvent::EVENT_DISPATCH_ERROR, array($this, errorProcess), 999 ); } @walterdalmut - www.corley.it - www.upcloo.com
  • Attach Post Processor to Actionspublic function postProcess(MvcEvent $e){ $routeMatch = $e->getRouteMatch(); $formatter = $routeMatch->getParam(formatter, false); $di = $e->getTarget()->getServiceLocator()->get(di); if ($formatter !== false) { if ($e->getResult() instanceof ZendViewModelViewModel) { if (($e->getResult()->getVariables())) { $vars = $e->getResult()->getVariables(); } else { $vars = null; } } else { $vars = $e->getResult(); } $postProcessor = $di->get($formatter . -pp, array( request => $e->getRequest(), response => $e->getResponse(), vars => $vars, )); $postProcessor->process(); return $postProcessor->getResponse(); } return null;} @walterdalmut - www.corley.it - www.upcloo.com
  • Example of JSON Post Processor<?php <?phpnamespace MainPostProcessor; namespace MainPostProcessor;/** abstract class AbstractPostProcessor * { */ protected $_vars = null;class Json extends AbstractPostProcessor private $_request = null;{ private $_response = null; public function process() { public function __construct $result = json_encode($this->_vars); (ZendHttpRequest $request, ZendHttpResponse $response, $vars = null) { $headers = $this->getResponse()->getHeaders(); $this->_vars = $vars; $headers->addHeaderLine(Content-Type, application/json); $this->_response = $response; $this->_request = $request; $this->getResponse()->setHeaders($headers); } $this->getResponse()->setContent($result); } public function getResponse()} { return $this->_response; } public function getRequest() { return $this->_request; } abstract public function process(); } @walterdalmut - www.corley.it - www.upcloo.com
  • ZF2 RESTful Modules Thanks for listening… Any questions? @walterdalmut - www.corley.it - www.upcloo.com