KEMBAR78
How I built web services in CakePHP | ODP
How I built web services in CakePHP
Amsterdam
2016
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
Agenda
System architecture
Version 1
Version 2
Version 3
CakePHP 2
CakePHP 2
CakePHP 3
System architecture
CMS
Web
Service
Client websites
The
Internet
ApiUpdatable
Driver
Plugins
Read-only
Queue
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
The Fat Controller
Version 1
Api Plugin
/api/v1
● Hard to maintain
● Lack of flexibility
● Not DRY
● No separation of
concerns
● Custom views
Version 1
ApiAuth Plugin
/api/v1
● No standards
● Open GET params
● No security
Version 1
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
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/
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
Version with prefixes
src/Controller/Api/V3/PackagesController.php
src/Controller/Api/V4/PackagesController.php
/api/v3/packages.json
/api/v4/packages.json
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/
Crud Index Action
Crud Index Action
Related data
Contain all the things
Version 3
Version 3
Filtering data
Match all the things
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!
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
Lessons learned
Don't
● Single controller
● Filter in controller
Do
● Routing prefixes
● Crud plugin
● Authentication
● Create separation
● Integration testing
Toolset
friendsofcake/crud
friendsofcake/search
admad/cakephp-jwt-auth
muffin/webservice
league/fractal
https://www.getpostman.com/
Consuming the API
Cake 2
Custom data source
http://book.cakephp.org/2.0/en/models/datasources.html
Muffin/WebService Cake 3 driver
http://jedistirfry.co.uk/blog/2015-09/connecting-to-a-web-service/
Consuming the API
Cake 3
Thanks!
Questions?
Please rate my talk
https://joind.in/talk/e2065
Attend your local PHP Usergroup! http://php.ug/
http://osmihelp.org/donate

How I built web services in CakePHP

Editor's Notes

  • #3 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.
  • #4 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!
  • #5 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
  • #6 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!
  • #7 If your controller looks like this, stop, and rethink
  • #8 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
  • #9 Who knows what past me was thinking with this one. Even the templates are in the other plugin!
  • #10 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!
  • #11 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
  • #12 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
  • #13 Neat code separation Can still inherit from ApiController Easy to run multiple versions from the same app
  • #14 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!
  • #15 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
  • #16 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
  • #17 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
  • #18 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
  • #19 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
  • #20 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
  • #21 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
  • #22 Postman client for testing your endpoints yourself
  • #23 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
  • #24 Service info configured in your app.php under Webservices config key Will return json entities directly from a cake 3 endpoint
  • #25 If you'd like to discuss anything in my talk, please come see me for a chat.