by Enrico Zimuel - Zend, a Rogue Wave Company
29 January 2016 - Antwerp (Belgium)
Enrico Zimuel (@ezimuel), developer since 1996. Senior Software Engineer in the R&D department of Zend a Rogue Wave Company. Research programmer at the Informatics Institute of Amsterdam University in 2006. Open source contributor, core team of Apigility and Zend Framework. TEDx and international speaker about programming. Co-founder of PHP User Group Torino (Italy).
API stands for "Application Programming Interface" and as a term, specifies how software should interact.
In this worskhop we are interested in Web APIs, those delivered over HyperText Transfer Protocol (HTTP).
REpresentational State Transfer (REST) is an architecture designed around the HTTP specification.
REST leverages HTTP's strengths, and builds on:
Talking about REST, the Richardson Maturity Model is often used to describe the concerns necessary when implementing a well-designed REST API
The usage of HTTP as communication layer
A format for data representation (e.g. JSON)
Basically a Remote Procedure Call (RPC)
URIs as unique identifiers for resources
For instance, the resource User can be identified by
http://domain/api/user[/:user_id]
where user_id is an optional parameter
Usage of HTTP verbs for operations on resources
CRUD | HTTP verbs |
CREATE | POST |
READ | GET |
UPDATE | PUT, PATCH* |
DELETE | DELETE |
* partial update
Linking between resources to indicate relationships (hypermedia)
GET /api/user/ezimuel
{
"_links": {
"self": {
"href": "http://domain/api/user/ezimuel"
},
"contacts": [
{ "href": "http://domain/api/user/mwop" },
{ "href": "http://domain/api/user/zeevs" }
]
},
"id": "ezimuel",
"name": "Enrico Zimuel"
}
JSON-HAL format
Scalable architecture
Very easy to consume
Reduce client/server coupling
Discoverability
GET /api/user/ezimuel
{
"_links": {
"self": {
"href": "http://domain/api/user/ezimuel"
}
}
"id": "ezimuel",
"name": "Enrico Zimuel"
}
{
"_links": {
"self": {
"href": "http://domain/api/user/ezimuel"
}
}
"id": "ezimuel",
"name": "Enrico Zimuel",
"_embedded": {
"contacts": [
{
"_links": {
"self": {
"href": "http://domain/api/user/mwop"
}
},
"id": "mwop",
"name": "Matthew Weier O'Phinney"
},
{
"_links": {
"self": {
"href": "http://domain/api/user/zeevs"
}
},
"id": "zeevs",
"name": "Zeev Suraski"
}
]
}
}
{
"_links": {
"self": {
"href": "http://domain/api/user?page=3"
},
"first": {
"href": "http://domain/api/user"
},
"prev": {
"href": "http://domain/api/user?page=2"
},
"next": {
"href": "http://domain/api/user?page=4"
},
"last": {
"href": "http://domain/api/user?page=133"
}
}
"count": 3,
"total": 498,
"_embedded": {
"users": [
{
"_links": {
"self": {
"href": "http://domain/api/user/mwop"
}
},
"id": "mwop",
"name": "Matthew Weier O'Phinney"
},
{
"_links": {
"self": {
"href": "http://domain/api/user/mac_nibblet"
}
},
"id": "mac_nibblet",
"name": "Antoine Hedgecock"
},
{
"_links": {
"self": {
"href": "http://domain/api/user/spiffyjr"
}
},
"id": "spiffyjr",
"name": "Kyle Spraggs"
}
]
}
}
Content-Type: application/problem+json
{
"detail": "The GET method has not been defined for individual",
"status": 405,
"title": "Method Not Allowed",
"type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"
}
Accept: application/hal+json, application/json
Agility uses two approaches:
v1
/userv1
+json Apigility supports three different authentication systems: HTTP Basic, HTTP Digest, and OAuth2
git clone https://github.com/ezimuel/php-benelux-apigility
cd php-benelux-apigility
composer install
php -S 0.0.0.0:8888 -t public/ public/index.php
/speaker[:/speaker_id]
/talk[:/talk_id]
CREATE TABLE speakers (
id INTEGER PRIMARY KEY,
name VARCHAR(80) NOT NULL,
title VARCHAR(80),
company VARCHAR(80),
url VARCHAR(255),
twitter VARCHAR(80)
);
CREATE TABLE talks (
id INTEGER PRIMARY KEY,
title TEXT,
abstract TEXT,
day TEXT,
start_time TEXT,
end_time TEXT
);
CREATE TABLE talks_speakers (
talk_id INTEGER NOT NULL,
speaker_id INTEGER NOT NULL
);
The database is stored in /data/db/conference.db
The Data Mapper is a class that interacts with the data model
It's consumed by REST resource to return Entities/Collection
Can be injected in the resource using ResourceFactory
Apigility offers the management of DBs using adapters
Support for PDO, MySQL, Oci8, IbmDb2, PgSQL, SqlSrv
Use the Zend\Db\Adapter component of ZF2
To check the solution of exercise 1:
git checkout -b exercise/1 origin/exercise/1
* use the Zend\Validator\Date with the options "format" to "Y-m-d"
To check the solution of exercise 2:
git checkout -b exercise/2 origin/exercise/2
Using the _embedded field format, add the following:
* Add a speakers field in TalkEntity to return a SpeakerCollection
To check the solution of exercise 3:
git checkout -b exercise/3 origin/exercise/3
Rate this talk at joind.in/talk/84a7e
More information on apigility.org
Contact me: enrico [at] zend.com
Follow me: @ezimuel
This work is licensed under a
Creative Commons Attribution-ShareAlike 3.0 Unported License.
I used reveal.js to make this presentation.