SlideShare a Scribd company logo
1 of 33
Designing CakePHP plugins for consuming APIs By @neilcrookes for CakeFest2010 www.neilcrookes.com github.com/neilcrookes
Contents Foundations CakePHP plugins, APIs, REST, HTTP, CakePHP HttpSocket, OAuth Design approach Traditional approach, issues with that, my solution Examples
Types of CakePHP plugins Mini apps Provide full functionality you can include in your app e.g. blog, store locator Extenders Extend your app with more functionality e.g. commentable & taggable Enhancers Enhance your apps existing functionality e.g. filter Wrappers Provide functionality to access 3rd party APIs
APIs Source: http://www.programmableweb.com/apis ,[object Object]
My work so far has been mainly consuming RESTful APIs so this presentation and examples will focus on REST
But concepts illustrated in the design approach section later on can be applied to any protocol,[object Object]
HTTP Send request <HTTP verb> <URI> HTTP/1.1 <Header 1 name>: <Header 1 value> ... <optional body> You’ll get some kind of response (hopefully) HTTP/1.1 <Status Code> <Status Message> <Header 1 name>: <Header 1 value> ... <optional body>
Simple HTTP GET Request & Response Request GET http://www.example.com/index.html HTTP/1.1 User-Agent: My Web Browser Response HTTP/1.1 200 OK Content-Type: text/html Content-Length: 70 <html> <head> <title>My Web Page</title> </head> <body> <h1>My Web Page</h1> </body> </html>
Simple HTTP POST Request & Response Request POST http://www.example.com/login HTTP/1.1 Content-Type: application/x-www-form-urlencoded Content-Length: 38 username=neilcrookes&password=abcd1234 Response HTTP/1.1 301 Moved Permanently Location: http://www.example.com/my_account
CakePHP’s HttpSocket Class cake/libs/http_socket.php ,[object Object],    App::import(‘Core’, ‘HttpSocket’);     $Http = new HttpSocket();     $response = $Http->request(array(     ‘method’ => ‘POST’,       ‘uri’ => array(         ‘host’ => ‘example.com’,         ‘path’ => ‘login’),       ‘body’ => array(         ‘username’ => ‘neilcrookes’,         ‘password’ => ‘abcd1234’))); ,[object Object],[object Object]
OAuth In summary, it allows users of a service (e.g. Twitter) to authorize other parties (i.e. your application) access to their accounts on that service, without sharing their password with the other parties. In reality, it means: a little bit of handshaking between your app and the service provider to get various string tokens redirecting the user to the service in order for them to authorize your app to access their account, so the user only signs in to the service, not your app. the service provides you with a token you can persist and use to make authorized requests to their service on behalf of the user In practice it’s just an extra header line (Authorization header) in the HTTP request which contains some arbitrary parameters e.g. timestamp a token that identifies your application to the API provider a signature string that signs the request and is a hash of various request parameters and the secret tokens you retrieved above Used by e.g. Twitter & Google APIs
HttpSocketOauth Usage example to tweet “Hello world!”: App::import('Vendor', 'HttpSocketOauth'); $Http = new HttpSocketOauth(); $response = $Http->request(array(   'method' => 'POST',   'uri' => array(     'host' => 'api.twitter.com',     'path' => '1/statuses/update.json'),   'auth' => array(     'method' => 'OAuth',     'oauth_token' => <oauth token>,     'oauth_token_secret' => <oauth token secret>,    'oauth_consumer_key' => <oauth consumer key>,     'oauth_consumer_secret' => <oauth consumer secret>),   'body' => array(     'status' => 'Hello world!'))); http://www.neilcrookes.com/2010/04/12/cakephp-oauth-extension-to-httpsocket/ http://github.com/neilcrookes/http_socket_oauth
Contents Foundations CakePHP plugins, APIs, REST, HTTP, CakePHP HttpSocket, OAuth Design approach Traditional approach, issues with that, my solution Examples
Traditional approach: DataSource Complex DataSource containing all the logic Call methods on the DataSource directly from your models or controllersor as implied by the example Twitter DataSource in the cook book: access DataSource methods through your models but include most of the logic in the DataSourcehttp://book.cakephp.org/view/1077/An-Example Works well for simple stuff This is how I started implementing
However... Does not scale well for large APIs Twitter has ~100 API calls available, all with a wide variety of options and parameters. The cook book Twitter DataSource partially implements 2 API calls and is 86 lines Does not exploit built-in CakePHP goodness Callbacks Validation Pagination Does not allow for multiple models (and therefore  multiple schemas) to use the same DataSource Didn’t feel right to me
So what does feel right? What operations are we actually doing? Reading data Creating and updating data Deleting data i.e. Find, save & delete What type of classes in CakePHP provide these methods?
Models Photo by memoflores, available under creative commons http://www.flickr.com/photos/memoflores/ And what should models be?...
FAT! Photo by cstreetus, available under creative commons http://www.flickr.com/photos/cstreetus/ Sorry but every other image I found through searching for “fat models” or “fat ladies” was completely inappropriate ;-)
So if we move our API calls into Model::find(), Model::save() and Model::delete() methods It feels like the right place We’re more familiar with interacting with these We can have lots of simple models classes to achieve scale, separation of concerns and different models can have different validation rules and schemas and we can collect them together in a plugin But...
But what about CakePHP goodness? Triggering callbacks beforeFind(), afterFind(), beforeSave(), afterSave(), beforeValidate(), beforeDelete(), afterDelete() Triggering validation Handling custom find types If we made the API calls directly in these methods and returned the response, to exploit this excellent built-in additional CakePHP functionality we’d have to trigger/code them manually We’d be duplicating loads of code from CakePHP’s core Model class. Not very DRY
To understand the solution, we must understand CakePHP Model internals Model methods like find(), save() and delete() accept various params such as conditions, data to save etc Handle custom find types for find() only Handle validation for save() only Trigger the before*() callbacks Call create(), read(), update() or delete() on that model’s DataSource Trigger the after*() callbacks Return the result
So what’s my solution for designing CakePHP plugins for consuming APIs? Plugin containing one model for each type of resource in the API e.g. TwitterStatus or YouTubeVideo Models implement find() (or actually more commonly just CakePHP custom find types), save() and delete() methods as appropriate These methods set the details of the request, i.e. The array that represents an HTTP request that HttpSocket::request() methods expects (as we saw earlier in this presentation) in a request property of your model, then calls the same method on the parent object i.e. Model. Cont...
Solution continued CakePHP Model class handles validation and custom find types, triggers callbacks etc then calls create(), read(), update() or delete() on the child model’s (your model’s) DataSource, and passes the model object Your model’s useDbConfig property should be set to a custom DataSource that you also include in your plugin Your DataSource implements the appropriate CRUD method(s) and issues the API call described in the model’s requestproperty, and returns the results
Hmmm, sounds complicated It’s not I’ve written a REST DataSource you can use (see later) All you have to do is create a model that has find() or save() methods, in which you set a request property to an array expected by HttpSocket::request() and call the same method on the parent.
E.g. Creating a tweet <?php class TwitterStatus extends AppModel {   public function save($data = null) {     $this->request = array(       'uri' => array(         'host' => 'api.twitter.com',         'path' => '1/statuses/update.json'),       'body' => array(         'status' => $data['TwitterStatus']['text']));     return parent::save($data);   } } ?>
Which you call like this ClassRegistry::init('Twitter.TwitterStatus')->save(array(   'TwitterStatus' => array(     'text' => “Hello world!”) )); ... from anywhere you like in your CakePHP application, e.g. In your Post model afterSave() method, thus automatically creating a tweet every time you create a new post.
RestSource http://www.neilcrookes.com/2010/06/01/rest-datasource-plugin-for-cakephp/ http://github.com/neilcrookes/CakePHP-ReST-DataSource-Plugin You can set your model’s useDbConfigparam to this DataSource, or you can write your own DataSource that extends this one E.g. Override RestSource::request() to add in the host key in the $model->request property if it’s the same for all API calls, then call parent::(request)
This diagram illustrates the flow through the methods an classes involved in creating a tweet https://docs.google.com/drawings/edit?id=1Aht7huICl9bhl2hWRdM0VdoaBePpJ0kXkceyQpAR8os&hl=en_GB&authkey=CISSqJkN
In summary By designing plugins like this you’re providing Simple (1 line) method calls to API functions That are familiar to all CakePHP bakers And easy to document You also get to exploit CakePHP goodness such as validation and callbacks etc You can have multiple models, one for each resource type on the API, each with it’s own schema (which the FormHelper uses) and validation rules
Contents Foundations CakePHP plugins, APIs, REST, HTTP, CakePHP HttpSocket, OAuth Design approach Traditional approach, issues with that, my solution Examples
Examples YouTube Twitter
Uploading a YouTube Video – you do ClassRegistry::init('Gdata.YouTubeVideo')->save(array(   'YouTubeVideo' => array(     'title' => 'Flying into Chicago Airport',     'description' => 'Filmed through the plane window coming in over the lake',     'category' => 'Travel',     'keywords' => 'Chicago, Plane, Lake, Skyline',     'rate' => 'allowed',     'comment' => 'allowed',     'commentVote' => 'allowed',     'videoRespond' => 'allowed',     'embed' => 'allowed',     'syndicate' => 'allowed',     'private' => 1,     'file' => array(       'name' => 'chicago 1 060.AVI',       'type' => 'video/avi',       'tmp_name' => 'C:indowsemphp6D66.tmp',       'error' => 0,       'size' => 5863102))));
Uploading a YouTube Video – plugin creates POST /feeds/api/users/default/uploads HTTP/1.1 Host: uploads.gdata.youtube.com Connection: close User-Agent: CakePHP Content-Type: multipart/related; boundary="Next_Part_4c801b22-52e8-4c70-961b-0534fba3b5b1“ Slug: chicago 1 060.AVI Gdata-Version: 2 X-Gdata-Key: key=<my developer key> Authorization: OAuth oauth_version="1.0",oauth_signature_method="HMAC-SHA1",oauth_consumer_key="anonymous",oauth_token=“<my oauth token>",oauth_nonce="fa4b6fc350e19f675f2e5660657e643c",oauth_timestamp="1283463971",oauth_signature="3fIXJ%2BmdV6KLk4zJYszR7M90lIg%3D“ Content-Length: 5864289 --Next_Part_4c801b22-52e8-4c70-961b-0534fba3b5b1 Content-Type: application/atom+xml; charset=UTF-8 <?xml version="1.0" encoding="utf-8"?> <entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">   <media:group>     <media:title type="plain">Flying into Chicago Airport</media:title>     <media:description type="plain">Filmed through the plane window, shows coming in over the lake</media:description>     <media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">Travel</media:category>     <media:keywords>Chicago, Plane, Lake, Skyline</media:keywords>     <yt:private/>   </media:group>   <yt:accessControl action="rate" permission="allowed"/>   <yt:accessControl action="comment" permission="allowed"/>   <yt:accessControl action="commentVote" permission="allowed"/><   <yt:accessControl action="videoRespond" permission="allowed"/>   <yt:accessControl action="embed" permission="allowed"/>   <yt:accessControl action="syndicate" permission="allowed"/> </entry>  --Next_Part_4c801b22-52e8-4c70-961b-0534fba3b5b1  Content-Type: video/avi Content-Transfer-Encoding: binary <binary file data>

More Related Content

What's hot

4 introduction-php-mvc-cakephp-m4-controllers-slides
4 introduction-php-mvc-cakephp-m4-controllers-slides4 introduction-php-mvc-cakephp-m4-controllers-slides
4 introduction-php-mvc-cakephp-m4-controllers-slidesMasterCode.vn
 
ACL in CodeIgniter
ACL in CodeIgniterACL in CodeIgniter
ACL in CodeIgnitermirahman
 
XamarinとAWSをつないでみた話
XamarinとAWSをつないでみた話XamarinとAWSをつないでみた話
XamarinとAWSをつないでみた話Takehito Tanabe
 
6 introduction-php-mvc-cakephp-m6-views-slides
6 introduction-php-mvc-cakephp-m6-views-slides6 introduction-php-mvc-cakephp-m6-views-slides
6 introduction-php-mvc-cakephp-m6-views-slidesMasterCode.vn
 
Request dispacther interface ppt
Request dispacther interface pptRequest dispacther interface ppt
Request dispacther interface pptTaha Malampatti
 
Codeigniter : Two Step View - Concept Implementation
Codeigniter : Two Step View - Concept ImplementationCodeigniter : Two Step View - Concept Implementation
Codeigniter : Two Step View - Concept ImplementationAbdul Malik Ikhsan
 
Using the new WordPress REST API
Using the new WordPress REST APIUsing the new WordPress REST API
Using the new WordPress REST APICaldera Labs
 
Building RESTful applications using Spring MVC
Building RESTful applications using Spring MVCBuilding RESTful applications using Spring MVC
Building RESTful applications using Spring MVCIndicThreads
 
Building Applications Using Ajax
Building Applications Using AjaxBuilding Applications Using Ajax
Building Applications Using Ajaxs_pradeep
 
An introduction to Laravel Passport
An introduction to Laravel PassportAn introduction to Laravel Passport
An introduction to Laravel PassportMichael Peacock
 
Rails 3 Beautiful Code
Rails 3 Beautiful CodeRails 3 Beautiful Code
Rails 3 Beautiful CodeGreggPollack
 
Creating REST Applications with the Slim Micro-Framework by Vikram Vaswani
Creating REST Applications with the Slim Micro-Framework by Vikram VaswaniCreating REST Applications with the Slim Micro-Framework by Vikram Vaswani
Creating REST Applications with the Slim Micro-Framework by Vikram Vaswanivvaswani
 
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...Caldera Labs
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 

What's hot (20)

4 introduction-php-mvc-cakephp-m4-controllers-slides
4 introduction-php-mvc-cakephp-m4-controllers-slides4 introduction-php-mvc-cakephp-m4-controllers-slides
4 introduction-php-mvc-cakephp-m4-controllers-slides
 
REST API Laravel
REST API LaravelREST API Laravel
REST API Laravel
 
ACL in CodeIgniter
ACL in CodeIgniterACL in CodeIgniter
ACL in CodeIgniter
 
Slim Framework
Slim FrameworkSlim Framework
Slim Framework
 
Web api
Web apiWeb api
Web api
 
XamarinとAWSをつないでみた話
XamarinとAWSをつないでみた話XamarinとAWSをつないでみた話
XamarinとAWSをつないでみた話
 
6 introduction-php-mvc-cakephp-m6-views-slides
6 introduction-php-mvc-cakephp-m6-views-slides6 introduction-php-mvc-cakephp-m6-views-slides
6 introduction-php-mvc-cakephp-m6-views-slides
 
Request dispacther interface ppt
Request dispacther interface pptRequest dispacther interface ppt
Request dispacther interface ppt
 
Codeigniter : Two Step View - Concept Implementation
Codeigniter : Two Step View - Concept ImplementationCodeigniter : Two Step View - Concept Implementation
Codeigniter : Two Step View - Concept Implementation
 
Using the new WordPress REST API
Using the new WordPress REST APIUsing the new WordPress REST API
Using the new WordPress REST API
 
Day01 api
Day01   apiDay01   api
Day01 api
 
Building RESTful applications using Spring MVC
Building RESTful applications using Spring MVCBuilding RESTful applications using Spring MVC
Building RESTful applications using Spring MVC
 
Building Applications Using Ajax
Building Applications Using AjaxBuilding Applications Using Ajax
Building Applications Using Ajax
 
An introduction to Laravel Passport
An introduction to Laravel PassportAn introduction to Laravel Passport
An introduction to Laravel Passport
 
Rails 3 Beautiful Code
Rails 3 Beautiful CodeRails 3 Beautiful Code
Rails 3 Beautiful Code
 
Creating REST Applications with the Slim Micro-Framework by Vikram Vaswani
Creating REST Applications with the Slim Micro-Framework by Vikram VaswaniCreating REST Applications with the Slim Micro-Framework by Vikram Vaswani
Creating REST Applications with the Slim Micro-Framework by Vikram Vaswani
 
Spring Mvc Rest
Spring Mvc RestSpring Mvc Rest
Spring Mvc Rest
 
Zend framework
Zend frameworkZend framework
Zend framework
 
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 

Similar to Designing CakePHP plugins for consuming APIs

Practical catalyst
Practical catalystPractical catalyst
Practical catalystdwm042
 
En story of cakephp2.0
En story of cakephp2.0En story of cakephp2.0
En story of cakephp2.0Hiroki Shimizu
 
Implementing Comet using PHP
Implementing Comet using PHPImplementing Comet using PHP
Implementing Comet using PHPKing Foo
 
ASP.NET MVC introduction
ASP.NET MVC introductionASP.NET MVC introduction
ASP.NET MVC introductionTomi Juhola
 
Php interview questions
Php interview questionsPhp interview questions
Php interview questionssekar c
 
Exploring Symfony's Code
Exploring Symfony's CodeExploring Symfony's Code
Exploring Symfony's CodeWildan Maulana
 
Webservices in SalesForce (part 1)
Webservices in SalesForce (part 1)Webservices in SalesForce (part 1)
Webservices in SalesForce (part 1)Mindfire Solutions
 
OpenSocial Intro
OpenSocial IntroOpenSocial Intro
OpenSocial IntroPamela Fox
 
Compass Framework
Compass FrameworkCompass Framework
Compass FrameworkLukas Vlcek
 
Http programming in play
Http programming in playHttp programming in play
Http programming in playKnoldus Inc.
 
RESTful SOA - 中科院暑期讲座
RESTful SOA - 中科院暑期讲座RESTful SOA - 中科院暑期讲座
RESTful SOA - 中科院暑期讲座Li Yi
 
Create a web-app with Cgi Appplication
Create a web-app with Cgi AppplicationCreate a web-app with Cgi Appplication
Create a web-app with Cgi Appplicationolegmmiller
 
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...Guillaume Laforge
 
Intro To Mvc Development In Php
Intro To Mvc Development In PhpIntro To Mvc Development In Php
Intro To Mvc Development In Phpfunkatron
 
ActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group PresentationActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group Presentationipolevoy
 

Similar to Designing CakePHP plugins for consuming APIs (20)

Practical catalyst
Practical catalystPractical catalyst
Practical catalyst
 
En story of cakephp2.0
En story of cakephp2.0En story of cakephp2.0
En story of cakephp2.0
 
Implementing Comet using PHP
Implementing Comet using PHPImplementing Comet using PHP
Implementing Comet using PHP
 
Manish
ManishManish
Manish
 
Php
PhpPhp
Php
 
ASP.NET MVC introduction
ASP.NET MVC introductionASP.NET MVC introduction
ASP.NET MVC introduction
 
CGI Presentation
CGI PresentationCGI Presentation
CGI Presentation
 
Php interview questions
Php interview questionsPhp interview questions
Php interview questions
 
Exploring Symfony's Code
Exploring Symfony's CodeExploring Symfony's Code
Exploring Symfony's Code
 
Webservices in SalesForce (part 1)
Webservices in SalesForce (part 1)Webservices in SalesForce (part 1)
Webservices in SalesForce (part 1)
 
OpenSocial Intro
OpenSocial IntroOpenSocial Intro
OpenSocial Intro
 
Php frameworks
Php frameworksPhp frameworks
Php frameworks
 
Compass Framework
Compass FrameworkCompass Framework
Compass Framework
 
Http programming in play
Http programming in playHttp programming in play
Http programming in play
 
RESTful SOA - 中科院暑期讲座
RESTful SOA - 中科院暑期讲座RESTful SOA - 中科院暑期讲座
RESTful SOA - 中科院暑期讲座
 
Java Servlets
Java ServletsJava Servlets
Java Servlets
 
Create a web-app with Cgi Appplication
Create a web-app with Cgi AppplicationCreate a web-app with Cgi Appplication
Create a web-app with Cgi Appplication
 
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
 
Intro To Mvc Development In Php
Intro To Mvc Development In PhpIntro To Mvc Development In Php
Intro To Mvc Development In Php
 
ActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group PresentationActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group Presentation
 

Recently uploaded

CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 

Recently uploaded (20)

CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 

Designing CakePHP plugins for consuming APIs

  • 1. Designing CakePHP plugins for consuming APIs By @neilcrookes for CakeFest2010 www.neilcrookes.com github.com/neilcrookes
  • 2. Contents Foundations CakePHP plugins, APIs, REST, HTTP, CakePHP HttpSocket, OAuth Design approach Traditional approach, issues with that, my solution Examples
  • 3. Types of CakePHP plugins Mini apps Provide full functionality you can include in your app e.g. blog, store locator Extenders Extend your app with more functionality e.g. commentable & taggable Enhancers Enhance your apps existing functionality e.g. filter Wrappers Provide functionality to access 3rd party APIs
  • 4.
  • 5. My work so far has been mainly consuming RESTful APIs so this presentation and examples will focus on REST
  • 6.
  • 7. HTTP Send request <HTTP verb> <URI> HTTP/1.1 <Header 1 name>: <Header 1 value> ... <optional body> You’ll get some kind of response (hopefully) HTTP/1.1 <Status Code> <Status Message> <Header 1 name>: <Header 1 value> ... <optional body>
  • 8. Simple HTTP GET Request & Response Request GET http://www.example.com/index.html HTTP/1.1 User-Agent: My Web Browser Response HTTP/1.1 200 OK Content-Type: text/html Content-Length: 70 <html> <head> <title>My Web Page</title> </head> <body> <h1>My Web Page</h1> </body> </html>
  • 9. Simple HTTP POST Request & Response Request POST http://www.example.com/login HTTP/1.1 Content-Type: application/x-www-form-urlencoded Content-Length: 38 username=neilcrookes&password=abcd1234 Response HTTP/1.1 301 Moved Permanently Location: http://www.example.com/my_account
  • 10.
  • 11. OAuth In summary, it allows users of a service (e.g. Twitter) to authorize other parties (i.e. your application) access to their accounts on that service, without sharing their password with the other parties. In reality, it means: a little bit of handshaking between your app and the service provider to get various string tokens redirecting the user to the service in order for them to authorize your app to access their account, so the user only signs in to the service, not your app. the service provides you with a token you can persist and use to make authorized requests to their service on behalf of the user In practice it’s just an extra header line (Authorization header) in the HTTP request which contains some arbitrary parameters e.g. timestamp a token that identifies your application to the API provider a signature string that signs the request and is a hash of various request parameters and the secret tokens you retrieved above Used by e.g. Twitter & Google APIs
  • 12. HttpSocketOauth Usage example to tweet “Hello world!”: App::import('Vendor', 'HttpSocketOauth'); $Http = new HttpSocketOauth(); $response = $Http->request(array( 'method' => 'POST', 'uri' => array( 'host' => 'api.twitter.com', 'path' => '1/statuses/update.json'), 'auth' => array( 'method' => 'OAuth', 'oauth_token' => <oauth token>, 'oauth_token_secret' => <oauth token secret>, 'oauth_consumer_key' => <oauth consumer key>, 'oauth_consumer_secret' => <oauth consumer secret>), 'body' => array( 'status' => 'Hello world!'))); http://www.neilcrookes.com/2010/04/12/cakephp-oauth-extension-to-httpsocket/ http://github.com/neilcrookes/http_socket_oauth
  • 13. Contents Foundations CakePHP plugins, APIs, REST, HTTP, CakePHP HttpSocket, OAuth Design approach Traditional approach, issues with that, my solution Examples
  • 14. Traditional approach: DataSource Complex DataSource containing all the logic Call methods on the DataSource directly from your models or controllersor as implied by the example Twitter DataSource in the cook book: access DataSource methods through your models but include most of the logic in the DataSourcehttp://book.cakephp.org/view/1077/An-Example Works well for simple stuff This is how I started implementing
  • 15. However... Does not scale well for large APIs Twitter has ~100 API calls available, all with a wide variety of options and parameters. The cook book Twitter DataSource partially implements 2 API calls and is 86 lines Does not exploit built-in CakePHP goodness Callbacks Validation Pagination Does not allow for multiple models (and therefore multiple schemas) to use the same DataSource Didn’t feel right to me
  • 16. So what does feel right? What operations are we actually doing? Reading data Creating and updating data Deleting data i.e. Find, save & delete What type of classes in CakePHP provide these methods?
  • 17. Models Photo by memoflores, available under creative commons http://www.flickr.com/photos/memoflores/ And what should models be?...
  • 18. FAT! Photo by cstreetus, available under creative commons http://www.flickr.com/photos/cstreetus/ Sorry but every other image I found through searching for “fat models” or “fat ladies” was completely inappropriate ;-)
  • 19. So if we move our API calls into Model::find(), Model::save() and Model::delete() methods It feels like the right place We’re more familiar with interacting with these We can have lots of simple models classes to achieve scale, separation of concerns and different models can have different validation rules and schemas and we can collect them together in a plugin But...
  • 20. But what about CakePHP goodness? Triggering callbacks beforeFind(), afterFind(), beforeSave(), afterSave(), beforeValidate(), beforeDelete(), afterDelete() Triggering validation Handling custom find types If we made the API calls directly in these methods and returned the response, to exploit this excellent built-in additional CakePHP functionality we’d have to trigger/code them manually We’d be duplicating loads of code from CakePHP’s core Model class. Not very DRY
  • 21. To understand the solution, we must understand CakePHP Model internals Model methods like find(), save() and delete() accept various params such as conditions, data to save etc Handle custom find types for find() only Handle validation for save() only Trigger the before*() callbacks Call create(), read(), update() or delete() on that model’s DataSource Trigger the after*() callbacks Return the result
  • 22. So what’s my solution for designing CakePHP plugins for consuming APIs? Plugin containing one model for each type of resource in the API e.g. TwitterStatus or YouTubeVideo Models implement find() (or actually more commonly just CakePHP custom find types), save() and delete() methods as appropriate These methods set the details of the request, i.e. The array that represents an HTTP request that HttpSocket::request() methods expects (as we saw earlier in this presentation) in a request property of your model, then calls the same method on the parent object i.e. Model. Cont...
  • 23. Solution continued CakePHP Model class handles validation and custom find types, triggers callbacks etc then calls create(), read(), update() or delete() on the child model’s (your model’s) DataSource, and passes the model object Your model’s useDbConfig property should be set to a custom DataSource that you also include in your plugin Your DataSource implements the appropriate CRUD method(s) and issues the API call described in the model’s requestproperty, and returns the results
  • 24. Hmmm, sounds complicated It’s not I’ve written a REST DataSource you can use (see later) All you have to do is create a model that has find() or save() methods, in which you set a request property to an array expected by HttpSocket::request() and call the same method on the parent.
  • 25. E.g. Creating a tweet <?php class TwitterStatus extends AppModel { public function save($data = null) { $this->request = array( 'uri' => array( 'host' => 'api.twitter.com', 'path' => '1/statuses/update.json'), 'body' => array( 'status' => $data['TwitterStatus']['text'])); return parent::save($data); } } ?>
  • 26. Which you call like this ClassRegistry::init('Twitter.TwitterStatus')->save(array( 'TwitterStatus' => array( 'text' => “Hello world!”) )); ... from anywhere you like in your CakePHP application, e.g. In your Post model afterSave() method, thus automatically creating a tweet every time you create a new post.
  • 27. RestSource http://www.neilcrookes.com/2010/06/01/rest-datasource-plugin-for-cakephp/ http://github.com/neilcrookes/CakePHP-ReST-DataSource-Plugin You can set your model’s useDbConfigparam to this DataSource, or you can write your own DataSource that extends this one E.g. Override RestSource::request() to add in the host key in the $model->request property if it’s the same for all API calls, then call parent::(request)
  • 28. This diagram illustrates the flow through the methods an classes involved in creating a tweet https://docs.google.com/drawings/edit?id=1Aht7huICl9bhl2hWRdM0VdoaBePpJ0kXkceyQpAR8os&hl=en_GB&authkey=CISSqJkN
  • 29. In summary By designing plugins like this you’re providing Simple (1 line) method calls to API functions That are familiar to all CakePHP bakers And easy to document You also get to exploit CakePHP goodness such as validation and callbacks etc You can have multiple models, one for each resource type on the API, each with it’s own schema (which the FormHelper uses) and validation rules
  • 30. Contents Foundations CakePHP plugins, APIs, REST, HTTP, CakePHP HttpSocket, OAuth Design approach Traditional approach, issues with that, my solution Examples
  • 32. Uploading a YouTube Video – you do ClassRegistry::init('Gdata.YouTubeVideo')->save(array( 'YouTubeVideo' => array( 'title' => 'Flying into Chicago Airport', 'description' => 'Filmed through the plane window coming in over the lake', 'category' => 'Travel', 'keywords' => 'Chicago, Plane, Lake, Skyline', 'rate' => 'allowed', 'comment' => 'allowed', 'commentVote' => 'allowed', 'videoRespond' => 'allowed', 'embed' => 'allowed', 'syndicate' => 'allowed', 'private' => 1, 'file' => array( 'name' => 'chicago 1 060.AVI', 'type' => 'video/avi', 'tmp_name' => 'C:indowsemphp6D66.tmp', 'error' => 0, 'size' => 5863102))));
  • 33. Uploading a YouTube Video – plugin creates POST /feeds/api/users/default/uploads HTTP/1.1 Host: uploads.gdata.youtube.com Connection: close User-Agent: CakePHP Content-Type: multipart/related; boundary="Next_Part_4c801b22-52e8-4c70-961b-0534fba3b5b1“ Slug: chicago 1 060.AVI Gdata-Version: 2 X-Gdata-Key: key=<my developer key> Authorization: OAuth oauth_version="1.0",oauth_signature_method="HMAC-SHA1",oauth_consumer_key="anonymous",oauth_token=“<my oauth token>",oauth_nonce="fa4b6fc350e19f675f2e5660657e643c",oauth_timestamp="1283463971",oauth_signature="3fIXJ%2BmdV6KLk4zJYszR7M90lIg%3D“ Content-Length: 5864289 --Next_Part_4c801b22-52e8-4c70-961b-0534fba3b5b1 Content-Type: application/atom+xml; charset=UTF-8 <?xml version="1.0" encoding="utf-8"?> <entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007"> <media:group> <media:title type="plain">Flying into Chicago Airport</media:title> <media:description type="plain">Filmed through the plane window, shows coming in over the lake</media:description> <media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">Travel</media:category> <media:keywords>Chicago, Plane, Lake, Skyline</media:keywords> <yt:private/> </media:group> <yt:accessControl action="rate" permission="allowed"/> <yt:accessControl action="comment" permission="allowed"/> <yt:accessControl action="commentVote" permission="allowed"/>< <yt:accessControl action="videoRespond" permission="allowed"/> <yt:accessControl action="embed" permission="allowed"/> <yt:accessControl action="syndicate" permission="allowed"/> </entry> --Next_Part_4c801b22-52e8-4c70-961b-0534fba3b5b1 Content-Type: video/avi Content-Transfer-Encoding: binary <binary file data>