RESTful modules in zf2

  • 7,844 views
Uploaded on

Just a simple introduction to RESTful modules in ZF2

Just a simple introduction to RESTful modules in ZF2

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
7,844
On Slideshare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
108
Comments
0
Likes
8

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • 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.

Transcript

  • 1. RESTful Modules in ZF2Walter Dal Mut – walter.dalmut@gmail.com - @walterdalmut https://github.com/wdalmut @walterdalmut - www.corley.it - www.upcloo.com
  • 2. 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
  • 3. 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
  • 4. 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
  • 5. 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
  • 6. 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
  • 7. 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
  • 8. 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
  • 9. 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
  • 10. 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
  • 11. 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
  • 12. 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
  • 13. 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
  • 14. 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
  • 15. 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
  • 16. 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
  • 17. 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
  • 18. 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
  • 19. 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
  • 20. 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
  • 21. 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
  • 22. 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
  • 23. 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
  • 24. 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
  • 25. 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
  • 26. 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
  • 27. 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
  • 28. ZF2 RESTful Modules Thanks for listening… Any questions? @walterdalmut - www.corley.it - www.upcloo.com