Successfully reported this slideshow.
Your SlideShare is downloading. ×

How I built web services in CakePHP

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Upcoming SlideShare
PHP Berkshire October 2015
PHP Berkshire October 2015
Loading in …3
×

Check these out next

1 of 24 Ad

More Related Content

Slideshows for you (20)

Similar to How I built web services in CakePHP (20)

Advertisement

How I built web services in CakePHP

  1. 1. How I built web services in CakePHP Amsterdam 2016
  2. 2. Introduction PHP Developer at UK Web Media in Weyhill, UK http://www.ukwm.co.uk Cyberstalk me! https://twitter.com/YellDavid https://github.com/davidyell http://careers.stackoverflow.com/davidyell http://uk.linkedin.com/in/davidyell #cakephp on Freenode IRC David Yell aka Neon1024
  3. 3. Agenda System architecture Version 1 Version 2 Version 3 CakePHP 2 CakePHP 2 CakePHP 3
  4. 4. System architecture CMS Web Service Client websites The Internet ApiUpdatable Driver Plugins Read-only Queue
  5. 5. Setup /api/v1 Api ApiAuth Yey! ● Plugin architecture ● Self-contained Boo! ● Single fat controller ● Lack of separation ● Less flexible Routing Request Response Plugins Version 1 v1 prefix
  6. 6. The Fat Controller Version 1
  7. 7. Api Plugin /api/v1 ● Hard to maintain ● Lack of flexibility ● Not DRY ● No separation of concerns ● Custom views Version 1
  8. 8. ApiAuth Plugin /api/v1 ● No standards ● Open GET params ● No security Version 1
  9. 9. Setup /api/v2 Yey! ● Shares existing code ● More generic ● Extensibility ● Per endpoint customisation Boo! ● Hard to create common filtering ● Too much code in AppController ● Lacks separation Routing Request Response Application Version 2 v2 prefix AppController ProductsController
  10. 10. API Design choices Pragmatic approach Complex queries but more complete responses Allows complete configured return Flexible filtering and sorting Specific use-cases Further reading, http://www.bravo-kernel.com/tags/api/
  11. 11. Version 3 Routing Request Response api prefix v3 route ApiAppController Crud plugin Custom Crud actions Contain class Filter class Yey! ● Crud automation ● Free sorting and pagination ● Code separation ● Extensible Boo! ● Complexity Setup /api/v3 ApiQuery Behavior
  12. 12. Version with prefixes src/Controller/Api/V3/PackagesController.php src/Controller/Api/V4/PackagesController.php /api/v3/packages.json /api/v4/packages.json
  13. 13. Crud plugin friendsofcake/crud Event driven scaffolding Be lazy Do less work ?? Profit http://www.bravo-kernel.com/2015/04/how-to-build-a-cakephp-3- rest-api-in-minutes/
  14. 14. Crud Index Action
  15. 15. Crud Index Action
  16. 16. Related data Contain all the things Version 3
  17. 17. Version 3 Filtering data Match all the things
  18. 18. Version 3 Example queries Get packages with related data, where line rental is included, from provider id 4, matching an associated Table field, sorted by price, on page 2. /api/v3/packages.json ?verbose=true &filter[line_rental_included]=true &filter[provider_id]=4 &filter[Related.something]=foo &site_id=n &limit=20 &page=3 &sort=price &direction=asc Free with Crud plugin!
  19. 19. Version 3 Example queries Get a specific list of packages in a certain order. /api/v3/packages.json ?id[0]=19 &id[1]=17 &id[2]=11 &id[3]=43 &site_id=n
  20. 20. Lessons learned Don't ● Single controller ● Filter in controller Do ● Routing prefixes ● Crud plugin ● Authentication ● Create separation ● Integration testing
  21. 21. Toolset friendsofcake/crud friendsofcake/search admad/cakephp-jwt-auth muffin/webservice league/fractal https://www.getpostman.com/
  22. 22. Consuming the API Cake 2 Custom data source http://book.cakephp.org/2.0/en/models/datasources.html
  23. 23. Muffin/WebService Cake 3 driver http://jedistirfry.co.uk/blog/2015-09/connecting-to-a-web-service/ Consuming the API Cake 3
  24. 24. Thanks! Questions? Please rate my talk https://joind.in/talk/e2065 Attend your local PHP Usergroup! http://php.ug/ http://osmihelp.org/donate

Editor's Notes

  • Thanks for voting on my talk, I really appreciate it.
    Nearly 10 years commercial experience, mostly agencies doing campaign work.
    Started with HTML on GeoCities.
    Self-taught in PHP, started with CakePHP on 1.3 in 2008 ish and am in the Friends of Cake group
    UKWM do campaign and affiliate marketing work, I work mostly on the telecoms sites comparing broadband, tv and phone
    All our stuff is CakePHP 2 or 3, I'm migrating stuff as and when I have time
    This is the first run of this presentation so be gentle!
    I will hopefully have some time at the end for questions.
  • It's what I do for my job
    v1 is the first api I ever built!
    It's a read only web service
    Built by myself, used by myself
    Work in progress
    We are silo'd at work, so you guys are doing my code review for me!
  • The web service driver is a Datasource in Cake 2, and a web service driver in Cake 3.
    The use-case is a centrally managed data-store
    ApiUpdatable has a queue to schedule updates from the client site
    It also has a shell run on a cron
    Thin clients pull data from the web service on render and use local cache
    Multiple versions of the API with clients being migrated over
  • First ever api I built
    A plugin seemed logical at the time
    Coded first rather than designing it
    Difficult containing deep associations, 4-5 levels
    Ended up filtering data in the view, so the pagination meta was wrong
    Index method in ApiController is 247 lines long!
  • If your controller looks like this, stop, and rethink
  • Not flexible enough to expand to cover new use-cases easily
    Plugin needs tagging and releasing
    Duplicating functionality which already exists in the application
    Manual work to create the views
  • Who knows what past me was thinking with this one.
    Even the templates are in the other plugin!
  • All base endpoint methods are in the AppController
    Overload the methods as needed
    Extended methods means filtering would be complex on a per endpoint basis
    Never even made it out of the branch!
  • Reqs:
    Allows for complex sorting and filtering combinations
    Makes my client implementation simple
    Full comparison table data
    Pragmatic approach, practice rather than theory
    Fulfils use-cases of complex full data returns
    Not using the RESTful routing
    Hidden the _matchingData
    Focus on simplicity for the client
    The utopian vision of everything being achievable
  • Controller inheritance
    Crud plugin makes it easy
    Custom actions to call behavour methods on the query
    Behaviour uses custom finders to modify query
    Uses the ORMs stackable finders feature
    Doesn't adhere to REST standard, pragmatic and solo! ;)
    Filter and contain classes implement an interface, and customised per endpoint
    As Jose said in the workshop, don't be scared to go outside the framework
    Related data class also deals with sortable whitelist
    Luckily I have only 5 endpoints, 2 primary ones
  • Neat code separation
    Can still inherit from ApiController
    Easy to run multiple versions from the same app
  • Can help you build a basic api in literally minutes!
    Comes with pagination and sorting out of the box
    Has various api listeners,
    Api
    ApiPaginator
    ApiQueryLog
    Search listener implements the friendsofcake/search plugin
    Not as complicated as it appears, I'm working on the docs, so any contributions welcome!
  • Copy and paste of the default crud action
    Just added some extra methods to hook into the query object
    The methods just look for the behaviour and call it's custom finders on the query
  • Example Crud index action method
    _table is the current table, proxied call to Controller::loadModel() in Crud core
    Just passing a Cake\ORM\Query object
    Awesome because it's lazy I can build the query programatically and execute it later
  • Relies on awesome Cake 3 ORM with closures in my contains to filter my associations
    Highly customisable
    Boss asked to remove pricing, comment out the line, job done, 2 mins – comment because I know he'll change his mind ;)
    Low impact, as it's tied to a single endpoint
    Lots of code though, so can look daunting
    Manages both Joins and Contains, as some fields must be joined for filtering and sorting
    Lives in src/Lib/Api/RelatedData
  • Build filters as an array in the url
    I can pass all the filters around by just passing the array
    Allow for highly complex filtering
    Flexible and easy for clients to understand
    Has custom field filters too such as minPrice and maxPrice which map to the price field
    Lives in src/Lib/Api/Filters
  • Might not want to expose your schema
    Could use a custom JSON view or use Fractal
    Can return a complete response for the client implementation
  • For affiliate marketing comparison tables we need things in an arbitrary order set in the client site CMS
    Again,
    - Might not want to expose your schema
    - Could use a custom JSON view or use Fractal
  • Routing prefixes good for versioning, as they can be nested! So why not an api prefix, with a v2 prefix and v3 prefix?
    Don't be constrained by the framework where it doesn't make sense.
    Not all of your code needs to fit into the framework, but check first!
    Theoretical paralysis, too much thinking not enough doing.
    Be pragmatic.
    Create a branch, try a thing, ditch it and start over.
    Three branches before sorting worked!
    Testing using json fixture files
  • Postman client for testing your endpoints yourself
  • Cake 2 ApiUpdatable behaviour swaps the datasource based on if the query has the ‘api’ => true option set in the find conditions using a callback
    Data returned as json array
  • Service info configured in your app.php under Webservices config key
    Will return json entities directly from a cake 3 endpoint
  • If you'd like to discuss anything in my talk, please come see me for a chat.

×