3 queries
• Count query with same filters but no pagination
• Query with filters, pagination & sorting, but only select
DISTINCT IDs
◦ Because JOIN + LIMIT = wrong number of root records
• Query all the data (with joins) by IDs and apply sorting
11
Slide 11
Slide 11 text
LIMIT
SELECT * FROM game
LEFT JOIN rating ON rating.game_id = game.id
WHERE game.price < 20
LIMIT 2;
12
id name price game_id score
1 Skyrim 19.99 1 9.1
1 Skyrim 19.99 1 8.9
2 Diablo 3 17.89 2 8.5
Slide 12
Slide 12 text
Upload
• Use tools, don't DIY (do it yourself).
• Client-side: Symfony
• Client-side (more dynamic): Plupload
• Step 1: upload temp file.
• Step 2: give file path to next API request.
• Server-side: Guzzle.
13
Slide 13
Slide 13 text
Plupload
var uploader = new plupload.Uploader({
runtimes: 'html5,html4',
max_file_size: '5mb',
url: '/api/upload',
filters: [{extensions: 'jpg,png,jpeg'}]
});
uploader.init();
14
Status codes
• Don't confuse API & HTTP codes
• 2xx success
• 3xx redirect
• 4xx client error
• 5xx server error
• Send API-specific code in body
16
Slide 16
Slide 16 text
Example of error
Status: 400
Content-Type: application/json; charset=UTF-8
{
"error": {
"code": 1001,
"message": "Price must be greater than 0."
}
}
17
Slide 17
Slide 17 text
Testing
Simpler than you think
Slide 18
Slide 18 text
HTTP
• Use Guzzle or built-in framework tool
• Generate HTTP request , compare output
19
Slide 19
Slide 19 text
Guzzle test
// tests/ApiProductTest.php
public function testGetOneProduct()
{
$client = new Client();
$response = $client->get('http://example.org/products/1', [
'exceptions' => false,
'headers' => ['Accept' => 'application/json']
]);
$this->assertEquals(200, $response->getStatusCode());
// ...
}
20
Testing tips
• Create separate database for tests
• Write tests before you code:
• TDD
• Contract between you and client dev
22
Slide 22
Slide 22 text
Authentication
Nooo, I hate that part! Someone else code it plz.
Slide 23
Slide 23 text
Multiple methods
• Don't send username/password in each request
◦ Especially with untrusted 3rd parties
◦ Especially if no SSL
• You can have multiple auth methods for one API
• Sessions similar to tokens
24
Slide 24
Slide 24 text
OAuth2
• SSL required (can be risky)
• Advanced features like access scope
• Can be overkill if you need basic features
• Private credentials
25
Slide 25
Slide 25 text
OAuth2 - conceptual diagram
26
User Client app
(php/js/mobile)
API
Request Forward
Validate
Create
token
Store
token
Login form
Login
token
user/pass
Slide 26
Slide 26 text
Digest
• Its own encryption
• Easy to implement
• No replay (nonce)
• Comes out-of-the-box with some frameworks
27
Refactoring to API
Don't rewrite all the legacy at once
Slide 29
Slide 29 text
Progressive rewrite
• Rewrite one component at a time
• Start with whatever has fewer dependencies (or critical)
• Delete dead code
• Copy production data for dev environment
30
Slide 30
Slide 30 text
Services vs libraries
• Services: GET /products?id=1,5
• Libraries:
• Bypass HTTP
• $db->getList( ["id" => "1,5"] );
• Can fetch without pagination
• Can hydrate to models
31
Slide 31
Slide 31 text
Implementation tips
Is this a good way to code it?
Slide 32
Slide 32 text
Libraries
• I use Symfony & Doctrine
• Aside from frameworks, I prefer small tools that don't do
too much magic
33
Slide 33
Slide 33 text
Reuse & standardize
• Goal: streamline endpoint creation
• Base controller for common request processing
• Base repository for querying with filters
• Keep things fully customizable
34
Slide 34
Slide 34 text
Performance
Make things faster. Much faster.
Slide 35
Slide 35 text
Benchmark
• Give Tideways or Blackfire a spin
• Make performance part of your test suite
• In dev/test mode, use a meta block
36
Performance tips
• Don't use lazy loading. Example: $product->getPhotos().
• Craft your own joins and carefully select fields.
• Avoid ORM built-in hydration for read operations.
• Use API keys even for public endpoints (DDoS
mitigation).
• Put stuff in Memcached/Redis (especially blocked keys).
• HTTP server can check headers
38
Slide 38
Slide 38 text
Useful links
• Standard API format
http://jsonapi.org/format/
• Digest implementation
http://php.net/manual/en/features.http-auth.php
• Symfony components
http://symfony.com/doc/current/components/index.html
• Book "Build APIs You Won't Hate"
https://leanpub.com/build-apis-you-wont-hate
39
Slide 39
Slide 39 text
Anna Filina
• Development: PHP, JS, etc.
• Fix problems: bugs, performance, etc.
• Workshops: testing, Symfony, AngularJS, API, etc.
• Advisor: testing strategy, legacy code, etc.
40