Building a Rest API with Zend Framework 2
 

Building a Rest API with Zend Framework 2

on

  • 24,226 views

This presentation covers building a Representational State Transfer (REST) API, starting off with a quick overview of what REST is, comparing it to other methods, using good practices, and building a ...

This presentation covers building a Representational State Transfer (REST) API, starting off with a quick overview of what REST is, comparing it to other methods, using good practices, and building a simple API in Zend Framework 2 using the AbstractRestfulController as well as looking at and solving API related challenges.

Statistics

Views

Total Views
24,226
Views on SlideShare
24,092
Embed Views
134

Actions

Likes
47
Downloads
386
Comments
6

6 Embeds 134

http://librosweb.es 63
https://twitter.com 34
http://www.mikestowe.com 33
http://tweetedtimes.com 2
http://www.linkedin.com 1
https://www.linkedin.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

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…
  • what is this $userAPIservice and which database should it suit?
    Are you sure you want to
    Your message goes here
    Processing…
  • Hello can you please post your module.config.php file here as when you say
    'Segmented Routes allow you to have dynamic routes.
    DO NOT include a default AcIon for your REST API endpoints' on page 47 it confused me. Sorry for being so stupid but I am trying to learn zend and this is my very first application
    Are you sure you want to
    Your message goes here
    Processing…
  • im using ZF2.2 and i had some routing issues until i changed setEventManager to this:

    public function setEventManager(EventManagerInterface $events)
    {
    parent::setEventManager($events);
    $events->attach('dispatch',Array($this,'checkOptions'),10);
    }
    Are you sure you want to
    Your message goes here
    Processing…
  • Whoops! Thank you guys! Wesley, you might also want to check out the 'Zend Framework 2 for Newbies' presentation, doesn't go indepth to a lot of things, but does go over more of the basics of getting a ZF2 app up and running! Thanks for pointing these things out :)
    Are you sure you want to
    Your message goes here
    Processing…
  • There is an small error on slide 49 - it should be:
    $this->params()->fromRoute(...)
    instead of $this->params->fromRoute(...)
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Building a Rest API with Zend Framework 2 Building a Rest API with Zend Framework 2 Presentation Transcript

  • Building  a  REST  API     with  Zend  Framework  2   January  17,  2014  
  • What  we’re  gonna  talk  about…   Overview  of  REST   Building  Your  API   •   What  is  the  purpose  of  an  API   •   SeLng  up  Your  Routes   •   Different  API  Techniques   •   SeLng  up  Your  Controllers     •   The  REST  Methodology   •   Handling  Headers   •   Components  of  REST   •   Handling  JSON   •   Good  PracIces   •   Not  so  Good  PracIces   •   AuthenIcaIon  and  OAuth      
  • What  is  an  API?   An  ApplicaIon  Program  Interface  (API)  is  a  set  of  rouInes,   protocols,  and  tools  for  building  soRware  applicaIons.    A   good  API  makes  it  easier  to  develop  a  program  by  providing   all  the  building  blocks,  which  a  developer  can  then  use  to   put  the  blocks  together.1    Web  APIs  allow  the  transmission   of  data  and  acIons  across  different  web  applicaIons  and   sites  securely  and  through  a  language     agnosIc  interface.   1  definiIon  by  
  • Code  and  Personal  Data  are  Secure  
  • Different  Types  of  APIs   There  are  several  different  methods  for  building  an  API,   however  the  three  leading  methods  are  using   RepresentaIonal  State  Transfer  (REST),    Remote  Procedure   Calls  (RPC),  and    Simple  Object  Access    Protocol  (SOAP).  
  • An  Overview  of  RPC   Remote  Procedure  Calls  work  in  some  instances,  but  as  an   API  causes  problems  through  Ight  coupling  that:   •  Requires  clients  to  know  procedure  names   •  Has  specific  procedure  parameters  and  order   •  Requires  a  URI  per  method/  funcIon  (ie  create,  edit,   delete)  
  • An  Overview  of  SOAP   While  once  widely  popular,  SOAP  has  quickly  lost  ground  to   REST  based  APIs.    SOAP  based  APIs:   •  Exposes  operaIons/  method  calls   •  Larger  packets  of  data,  XML  based   •  All  calls  sent  through  POST   •  Can  be  stateless  or  stateful   •  WSDL  –  Web  Service  DefiniIons  
  • SOAP  Sample  Request   <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/stock"> <m:GetStockPrice> <m:StockName>IBM</m:StockName> </m:GetStockPrice> </soap:Body> </soap:Envelope> h`p://www.w3schools.com/soap/soap_example.asp  
  • SOAP  Sample  Response   <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Body xmlns:m="http://www.example.org/stock"> <m:GetStockPriceResponse> <m:Price>34.5</m:Price> </m:GetStockPriceResponse> </soap:Body> </soap:Envelope> h`p://www.w3schools.com/soap/soap_example.asp  
  • An  Overview  of  REST   REST  on  the  other  hand  has  gained  in  popularity  due  to  its   simplicity,  reduced  transfer  requirements,  and  usage  of  JSON.     REST:   •  Returns  data,  doesn’t  expose  methods   •  Supports  XML  and  JSON   •  Uses  explicit  HTTP  Verbs   •  Point  to  point  connecIons   •  Ajax  (JavaScript)  Friendly   •  Stateless  
  • REST  JSON  Sample  Request   {"user":{"firstName":"John","lastName":"Smith","e mail":"john.smith@pocahontas.com"}! REST  JSON  Sample  Response   {"user":{"firstName":"John","lastName":"Smith","e mail":"john.smith@pocahontas.com"},"_links":{"edi t":["href","http://www.mysite.com/api/user/1 0"],"message":["href","http://www.mysite.com/a pi/user/10/message"]}}!
  • REST  vs.  SOAP   REST   SOAP   •  Returns  data   •  Exposes  operaIons/  method  calls   •  Supports  XML  and  JSON   •  All  calls  sent  through  POST   •  Uses  CRUD/  HTTP  Verbs   •  Larger  packets  of  data,  XML  based   •  Point  to  point  connecIons   •  Can  be  stateless  or  stateful   •  Ajax  (JavaScript)  Friendly   •  WSDL  Support   •  Stateless       Advantage  goes  to…  
  • Arguments  against  REST   •  REST  APIs  are  difficult  to  build  and  maintain   •  REST  is  not  secure  (anyone  can  access  it)   •  There  are  no  strict  standards  for  REST  APIs   •  REST  services  are  not  reliable  
  • Arguments  against  REST   •  REST  APIs  are  difficult  to  build  and  maintain   Um,  we’re  going  to  build  one  in  thirty  minutes…    And  as   REST  has  gained  in  popularity  there  are  more  tools  to  help   keep  documentaIon  up  to  date.    As  long  as  basic  guidelines   are  followed  REST  APIs  can  be  maintained  and     provide  backwards  compaIbility.   Read  how  we  do  it  @   h`p://bit.ly/1cCEYjC  
  • Arguments  against  REST   •  REST  is  not  secure  (anyone  can  access  it)   There  are  many  precauIons  we  can  take  to  ensure  our   REST  API  only  serves  those  who  we  want  to  have  access   to  the  data,  including  OAuth  tokens  and  IP  restricIons.     However,  it’s  important  to  remember  that  like     anything,  JavaScript/  AJAX  should  only  be  used  to     make  calls  to  public  or  insensiIve  data.  
  • Arguments  against  REST   •  There  are  no  strict  standards  for  REST  APIs   This  is  true  as  there  is  no  governing  body  for  REST.     However,  we  will  be  going  over  some  general   guidelines  that  should  be  used  when  building  your   API  and  as  long  as  these  are  followed  your   API  should  be  totally  awesome.  
  • Arguments  against  REST   •  REST  services  are  not  reliable   REST  services  are  just  as  reliable  as  SOAP  APIs  when  the   proper  checks  are  implemented  on  the  client’s  side.     These  should  include  checking  the  request  headers   returned  by  CURL  requests.    For  this  reason  it  is   important  to  make  sure  you  are  using  the  correct   response  codes  and  giving  easy  to  understand     error  messages.  
  • A  Good  REST  API  Offers   •  Generality  –  language  agnosIc   •  Familiarity  –  developers  are  used  to  it   •  Scalability  –  can  grow  with  usage/  demand   •  SegmentaIon  –  secIons  can  be  updated  independently   •  Speed  –  low  data  transfer,  cacheable   •  Security  –  personal  data  remains  protected   •  EncapsulaIon  –  ability  to  send  data  as  objects  
  • REST  APIs  provide  a  concrete  barrier  
  • A  Good  REST  API  Uses  Explicit  HTTP  Verbs   Create  –  POST   Read  –  GET   Update  –  PUT   Delete  -­‐  DELETE  
  • A  Good  REST  API   Is  built  for  longevity  and  designed   to  evolve…  
  • “  so#ware  design  on  the  scale  of  decades:  every   detail  is  intended  to  promote  so#ware   longevity  and  independent  evolu8on.  Many  of   the  constraints  are  directly  opposed  to  short-­‐ term  efficiency.  Unfortunately,  people  are   fairly  good  at  short-­‐term  design,  and  usually   awful  at  long-­‐term  design  ”   -­‐  Dr.  Roy  Fielding  
  • A  Good  REST  API  Uses   Hypermedia   As   The   Engine   Of   ApplicaIon   State  
  • A  Good  REST  API  Uses   Hypermedia   As   The   Engine   Of   ApplicaIon   State   HATEOAS  relies  on  the  concept   that  applicaIons  will  change,   data  required  will  change,  and   paths  can  change.    However,   these  changes  should  not  effect   exisIng  clients.    Hypermedia  is   stressed  over  a  server   oriented  architecture.  
  • A  Good  REST  API  Uses   Hypermedia   As   The   Engine   Of   ApplicaIon   State   In  order  to  accommodate  these   changes  HATEOAS  not  only  sends   back  the  data  requested,  but  the   next  possible  acIons  as  urls,  this   allows  the  client’s  applicaIon  to   be  dynamic  while  accommodaIng   any  updates  to  the  API  itself,   prevenIng  V1,  V2,  V3     endpoints  
  • A  Good  REST  API  Uses   Hypermedia   ApplicaIon   Language   Hypermedia  ApplicaIon  Language   provides  a  format  for  describing   addiIonal  resources  (ie  links)  using  a   _links -> item -> connection type => url grouping.       Content  type:  applicaXon/hal+json      
  • Using  HATEOAS   {"data":{"user":{"fname":"first","lname":"last"}}, "_links":{ "edit":{"href":"/api/user/id/1"}, "message":{"href":"/api/message/id/1"} },"id":"1"} (Sample  JSON  Response)  
  • A  Good  REST  API  Uses   Hypermedia   As   The   Engine   Of   ApplicaIon   State   By  sending  back  the  next  possible   acIons  we  are  able  to  modify  the   endpoints  without  breaking   backwards  compaIbility…    Let’s   say  we  now  required  the  last   name  in  the  message  endpoint,   just  to  prevent  accidental     message  from  being     sent…  
  • Using  HATEOAS   {"data":{"user":{"fname":"first","lname":"last"}}, "_links":{ "edit":{"href" : "/api/user/id/1"}, "message":{"href" : "/api/message/id/1/lname/last"} }," id":"1"} We  can  update  the  endpoint  in  the  response  for  our  clients,   allowing  them  to  use  the  dynamic  endpoint  to  perform  the   acIon,  prevenIng  any  backwards  compaIbility  breaks!    
  • Use  JSON  instead  of  XML   •  Be`er  Language  Support     •  Lightweight  (much  less  code  than  XML)       {"object1":{"object":{"string":"rock","string2":"   star"}},"object2":{"string":"hello","string2":   "world"},"string":"json is cool"}     •  Object  Oriented  by  nature     •  Simple  to  encode/  decode   To  encode/  decode  JSON  in  PHP  simply  use  the  json_encode()  and     json_decode() funcIons!    Many  frameworks  also  have  JSON  libraries   that  take  care  of  all  of  the  error  checking  for  you  as  well!  
  • Use  AuthenXcaXon  Tokens   •  Users  should  be  provided  with  a  unique   API  key/  idenIfier  that  allows  you  to  track,   limit,  and  enable  features   •  An  OAuth  token  should  be  used  to  link  API   keys  to  accounts  instead  of  requesIng   account  usernames  and  passwords  
  • Thro^le  API  Key  Usage   Be  sure  to  place  limits  on  the  number  of  calls/  queries  an   API  key  can  make  per  hour  or  per  day  to  prevent  your   applicaIon  from  becoming  bogged  down  and  suscepIble   to  DOS  a`acks.     This  risk  can  also  be  reduced  by  ensuring  your   API  is  operaIng  within  the  cloud  and  has  the   ability  to  scale  to  increased  traffic  demands.  
  • OAuth  Tokens   Tokens  help  prevent  misuse  of  the  system  and  limit   access  to  the  control  panel.    Usernames  and  passwords   allow  hackers  to  go  in  beyond  the  API,  oRen  accessing   billing  and  profile  informaIon  that  exposes  your  clients   to  catastrophic  damage  should  this  informaIon     fall  into  the  wrong  hands  
  • Use  HTTP  Status  Codes   Proper  use  of  HTTP  status  codes  give  your  users  immediate   feedback  on  the  result.    Some  of  the  more  widely  used  Header   codes  include:     •  •  •  •  •  •  •  •  •  200  –  OK   201  –  Created   304  –  Not  modified   400  –  Bad  Request   401  –  Not  Authorized   403  –  Forbidden   404  –  Page/  Resource  Not  Found   405  –  Method  Not  Allowed   500  –  Internal  Server  Error  
  • Use  HTTP  Status  Codes   You  probably  shouldn’t  use  these…       •  418  –  I’m  a  teapot   •  420  –  Keep  your  calm   Status  Code  420  has  gained  popularity  as  it  is  saIrically  returned  by   Twi`er  when  there’s  been  too  many  requests,  however  the  proper   response  code  for  “too  many  requests”  would  be  429.      
  • Use  DescripXve  Error  Messages   Error  messages  should  give  a  clear  descripIon  of  what  went  wrong   and  how  the  client  can  fix  their  code  to  avoid  the  error  in  the   future.     Providing  a  link  to  addiIonal  informaIon  and  live  debugging   examples  is  oRen  extremely  useful  to  developers,  and  allows  your   error  messages  to  be  more  compact,  but  requires  you  to  keep   addiIonal  documentaIon  up  to  date  for  your  users.  
  • Use  DescripXve  Error  Messages   These  are  not  good  error  messages:     •  Something  went  wrong     •  Could  not  complete  acIon     •  Invalid  parameters     •  Hey  look,  it’s  a  rocket.  
  • Use  DescripXve  Error  Messages   Good  Error  Messages:     •  The  AuthenIcaIon  token  is  not  recognized,  learn   more  at  h`p://…     •  A  User  ID  is  required  to  perform  this  acIon,  learn   more  at  h`p://…     •  Error  Code  313.    Read  more  at  h`p://…  
  • Remember!   DO  NOT  BREAK  BACKWARDS  COMPATIBILITY.    Make   sure  whatever  updates  you  make  to  your  API  do  not   cause  problems  for  your  exisIng  clients.     It  is  ideal  to  have  unit  tests  running  against  your   API  to  ensure  changes  do  not  cause  negaIve     or  unforeseen  consequences.  
  • Versioning  (ie:  /api/v2/…)   For  this  reason  I  am  not  a  fan  of  “versioning”  your  API.     All  releases  should  be  backwards  compaIble  so  that  your   users  do  not  need  to  know  which  version  they  are  trying   to  access!    Imagine  if  you  versioned  your  website!     The  excepIon  to  this  is  a  complete  rewrite  of     your  API,  in  which  case  the  old  API  should  sIll     be  supported  unIl  clients  are  migrated.  
  • That’s  awesome!       Now  let’s  write     some  code…  
  • Step  1  –  Install  ZF2   On  the  chance  that  you  don’t  already  have  Zend   Framework  2  installed,  let’s  get  it  up  and  running.     We’re  going  to  assume  you  have  PHP  (php.net),  Git   (git-­‐scm.com)  and  Composer  (getcomposer.org)   already  installed.  
  • Installing  ZF2   1.  Create  directory  on  your  web  server  and  move  into  it   mkdir apiproject cd apiproject 2.  IniIalize  Git,  add  the  Skeleton  Repository,  and  Download   git init git remote add https://github.com/zendframework/ZendSkeletonApplication.git source git pull source master 3.  Run  Composer   php composer.phar install
  • Setup  the  View  JSON  Strategy   Add  the  ViewJsonStrategy  to  the  strategies  array  within  the   view_manager  in  moduleApplicaIonconfigmodule.config.php   'view_manager' => array( 'strategies' => array( 'ViewJsonStrategy', ), 'display_not_found_reason' => true, 'display_exceptions' => true, 'doctype' => 'HTML5', /* … */ ),!
  • Setup  the  Controller   Add  the  UserController  to  the  invokables  array  within  controllers  in   moduleApplicaIonconfigmodule.config.php   'controllers' => array( 'invokables' => array( 'ApplicationControllerIndex' => 'ApplicationControllerIndexController', 'ApplicationControllerUser' => 'ApplicationControllerUserController' ), ),! Remember  the  alias  (leR)  you  give  your  controller  as   we  will  use  that  to  setup  our  routes!  
  • Sefng  up  Routes   Add  routes  to  moduleApplicaIonconfigmodule.config.php  where   “ApplicaIon”  is  the  module  that  will  be  the  API  library.   // Segmented Route for APIs 'user' => array( 'type' => 'Segment', 'options' => array( 'route' => '/api/user[/:id]', 'defaults' => array( 'controller' => 'ApplicationControllerUser', ), ), ),! Segmented  Routes  allow  you  to  have  dynamic  routes.      DO  NOT  include  a  default  AcIon  for  your  REST  API  endpoints  
  • The  AbstractResgulController   Zend  Framework  2  comes  with  an  abstract  controller  for   creaIng  a  REST  API  built  in.         The  AbstractRestulController  can  be  found  in  the     vendor/zendframework/zendframework/library/Zend/MVC/Controller/ directory.     Note  –  you  should  not  modify  this  file  
  • The  AbstractResgulController   The  abstract  controller  comes  with  the  following  methods,   all  set  to  return  header  code  405  –  method  not  allowed:     •  create($data)   •  update($id,  $data)   •  delete($id)   •  replaceList($data)   •  deleteList()   •  patch($id,  $data)   •  get($id)   •  patchList($data)   •  getList()   •  opIons()    
  • Sefng  up  the  User  Controller   Extending  the  AbstractRestulController  we  can  setup   moduleApplicationsrcApplicationControllerUserController.php For  this  class  we  will:     •  Set  the  opIons/  header  permissions   •  Create  an  event  listener   •  Start  building  our  API  methods      
  • Sefng  up  the  UserController   <?php namespace ApplicationController; use ZendMvcControllerAbstractRestfulController; use ZendViewModelJsonModel; class UserController extends AbstractRestfulController { } !
  • Setup  OpXons   class UserController extends AbstractRestfulController { protected $collectionOptions = array('GET', 'POST'); protected $resourceOptions = array('GET', 'PUT', 'DELETE'); protected function _getOptions() { if ($this->params->fromRoute('id', false)) { // we have an ID, return specific item return $this->resourceOptions; } // no ID, return collection return $this->collectionOptions; } } ! We’ll  use  the  _getOpIons()  method  in  the  opIons()  and   checkOpIons()  methods  
  • Returning  Available  OpXons   public function options() { $response = $this->getResponse(); // If in Options Array, Allow $response->getHeaders() ->addHeaderLine('Allow', implode(',', $this->_getOptions())); // Return Response return $response; }!
  • Adding  an  Event  Listener   public function setEventManager(EventManagerInterface $events) { // events property defined in AbstractController $this->events = $events; // Register the listener and callback method with a priority of 10 $events->attach('dispatch', array($this, 'checkOptions'), 10); }! The  event  listener  will  check  the  header  when  dispatched  to  see  if   the  behavior/  h`p  verb  being  a`empted  is  allowed  for  the   resource/  collecIon.    If  it  isn’t,  the  checkOpIons()  method  will  kill   the  process  and  return  a  status  code  of  405  to  inform  the  user  the   method  a`empted  is  not  allowed.  
  • Add  Event  Listener  Method   public function checkOptions($e) { if (in_array($e->getRequest()->getMethod(), $this->_getOptions())) { // Method Allowed, Nothing to Do return; } }! // Method Not Allowed $response = $this->getResponse(); $response->setStatusCode(405); return $response;
  • Add  AcXon  Methods   public function create($data) { // get created service to handle user creation // in this case userAPIService extends UserService and // adds in the _links or available actions to the result $userAPIService = $this->getServiceLocator()->get('userAPIService'); $result = $userAPIService->create($data); $response = $this->getResponse(); $response->setStatusCode(201); // Send Data to the View return new JsonModel($result); }!
  • Curl  –X  POST  Request  Response  
  • Add  AcXon  Methods   public function update($id, $data) { // get created service to handle user updates // in this case userAPIService extends UserService and // adds in the _links or available actions to the result $userAPIService = $this->getServiceLocator()->get('userAPIService'); $result = $userAPIService->update($id, $data); $response = $this->getResponse(); $response->setStatusCode(200); // Send Data to the View return new JsonModel($result); }!
  • Add  AcXon  Methods   public function deleteList() { $response = $this->getResponse(); $response->setStatusCode(400); $result = array( 'Error' => array( 'HTTP Status' => '400', 'Code' => '123', 'Message' => 'A user ID is required to delete a user', 'More Info' => 'http://www.mysite.com/api/docs/user/delete', ), ); return new JsonModel($result); }! In  most  cases  you’re  going  to  want  to  prevent  clients  from   uIlizing  the  DELETE  HTTP  verb  without  providing  an  ID.    In     the  event  they  try  to  access  it  generically,  they  will  go  to  the   deleteList()  method.  
  • Curl  –X  DELETE  Request  Response  
  • You  now  have  a  funcXonal  API!   You  can  conInue  to  use  the  following  methods  (and  some   others)  to  build  your  API  Controllers!     •  create($data)   •  update($id,  $data)   •  delete($id)   •  replaceList($data)   •  deleteList()   •  patch($id,  $data)   •  get($id)   •  patchList($data)   •  getList()   •  opIons()    
  • Remember…   You  will  want  to  add  more  features  including  OAuth  2  and   thro`ling.    You  can  easily  do  this  by  creaIng  your  own   abstract  class  that  extends  the  AbstractRestulController,   or  by  taking  advantage  of  a  Zend  Framework  2  REST   Skeleton  App  (available  on  GitHub)  
  • More  Resources   You  can  learn  more  about  REST  APIs  and  Zend  Framework   2  by  visiIng  the  following:     •  REST  API  Tutorial  -­‐  h`p://www.restapitutorial.com/   •  Apigee  REST  Design  (PDF)  -­‐  h`p://bit.ly/13vZXAL     •  ZF2  GeLng  Started  -­‐  h`p://bit.ly/17Wgmun     •  MWOP  ZF2  REST  -­‐  h`p://bit.ly/19rmk9M     •  Hounddog  ZF2  REST  -­‐  h`p://bit.ly/12fVW0x  
  • A  Final  Thought…   A  good  API  is  harder  for  your  clients  to   implement…   …but  easier  for  them  (and  you)  to   maintain.    SDKs  save  lives.    
  • THANK YOU. A big thank you to Constant Contact for making this presentation possible @mikegstowe @ctct_api visit  mikestowe.com/slides  for  more  on  PHP  and  Web  Development