How I built web services in CakePHP
at UK Web Media
in Weyhill, UK
#cakephp on Freenode IRC
● Plugin architecture
● Single fat controller
● Lack of separation
● Less flexible
● Hard to maintain
● Lack of flexibility
● Not DRY
● No separation of
● Custom views
● No standards
● Open GET params
● No security
Shares existing code
● Per endpoint customisation
Hard to create common filtering
● Too much code in AppController
API Design choices
Complex queries but more complete responses
Allows complete configured return
Flexible filtering and sorting
Custom Crud actions
Contain class Filter class
● Crud automation
● Free sorting and pagination
● Code separation
Version with prefixes
Event driven scaffolding
Do less work
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.
Free with Crud plugin!
Get a specific list of packages in a certain order.
● Single controller
● Filter in controller
● Routing prefixes
● Crud plugin
● Create separation
● Integration testing
Consuming the API
Custom data source
Muffin/WebService Cake 3 driver
Consuming the API
Please rate my talk
Attend your local PHP Usergroup! http://php.ug/
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&apos;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&apos;s what I do for my job v1 is the first api I ever built! It&apos;s a read only web service Built by myself, used by myself Work in progress We are silo&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;ll change his mind ;) Low impact, as it&apos;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&apos;t be constrained by the framework where it doesn&apos;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’ =&gt; 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&apos;d like to discuss anything in my talk, please come see me for a chat.