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.
13
Slide 14
Slide 14 text
LIMIT
SELECT * FROM game
LEFT JOIN rating ON rating.game_id = game.id
WHERE game.price < 20
LIMIT 2;
14
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 15
Slide 15 text
Upload
• Use tools, don't DIY (do it yourself).
• Client-side: Plupload
◦ Step 1: upload temp file.
◦ Step 2: give file path to next API request.
• Server-side: Guzzle.
15
Slide 16
Slide 16 text
Plupload
var uploader = new plupload.Uploader({
runtimes: 'html5,html4',
max_file_size: '5mb',
url: '/api/upload',
filters: [{extensions: 'jpg,png,jpeg'}]
});
uploader.init();
16
Status codes
• Don't confuse API & HTTP codes.
• 2xx success.
• 3xx redirect.
• 4xx client error.
• 5xx server error.
• Send API-specific code in body.
18
Slide 19
Slide 19 text
Example of error
Status: 400
Content-Type: application/json; charset=UTF-8
{
"errors": {[
"code": 1001,
"message": "Price must be greater than 0."
]}
}
19
Slide 20
Slide 20 text
Testing
Simpler than you think
Slide 21
Slide 21 text
HTTP
• Use Guzzle or built-in framework tools.
• Generate HTTP request , compare output.
21
Slide 22
Slide 22 text
Guzzle test
// tests/ApiProductTest.php
public function test_GetOneProduct_ReturnsSuccess()
{
$client = new Client();
$response = $client->get('http://example.org/products/1', [
'exceptions' => false,
'headers' => ['Accept' => 'application/json']
]);
$this->assertEquals(200, $response->getStatusCode());
// ...
}
22
Testing tips
• Create separate database for tests.
• Write tests before you code:
◦ TDD.
◦ Contract between you and client dev.
24
Slide 25
Slide 25 text
Authentication
Nooo, I hate that part! Someone else code it plz.
Slide 26
Slide 26 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.
26
Slide 27
Slide 27 text
OAuth2
• SSL required (can be risky).
• Advanced features like access scope.
• Can be overkill if you need basic features.
• Private credentials.
27
Slide 28
Slide 28 text
OAuth2 - conceptual diagram
28
User Client app
(php/js/mobile)
API
Request Forward
Validate
Create
token
Store
token
Login form
Login
token
user/pass
Slide 29
Slide 29 text
Digest
• Its own encryption.
• Easy to implement.
• No replay (nonce).
• Comes out-of-the-box with some frameworks.
29
Refactoring to API
Don't rewrite all the legacy at once
Slide 32
Slide 32 text
Progressive rewrite
• Rewrite one component/module at a time.
• Start with whatever has fewer dependencies (or critical).
• Delete dead code.
• Copy production data for dev environment.
32
Slide 33
Slide 33 text
Services vs libraries
• Services: GET /products?id=1,5
• Libraries /classes:
• Bypass HTTP
• $table->getApiList( ["id" => "1,5"] );
• Can fetch without pagination.
• Can hydrate to models.
33
Slide 34
Slide 34 text
Implementation tips
Is this a good way to code it?
Slide 35
Slide 35 text
Libraries
• I use MVC frameworks & ORMs.
• Aside from frameworks, I prefer small tools that don't do
too much magic.
35
Slide 36
Slide 36 text
Reuse & standardize
• Goal: streamline endpoint creation.
• Automate request parameters extraction.
• Automate query generation based on parameters.
• Keep things fully customizable.
• Decouple from framework.
36
Slide 37
Slide 37 text
Performance
Make things faster. Much faster.
Slide 38
Slide 38 text
Benchmark
• Give Tideways or Blackfire a spin.
• Make performance part of your test suite.
• In dev/test mode, use a meta block.
38
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.
40
Slide 41
Slide 41 text
Performance tips
• Use API keys even for public endpoints (DDoS
mitigation).
• Put stuff in Memcached/Redis (especially blocked keys).
• HTTP server can check headers.
41
Slide 42
Slide 42 text
Useful links
• Standard API format
http://jsonapi.org/format/
• Digest implementation
http://php.net/manual/en/features.http-auth.php
• Book "Build APIs You Won't Hate"
https://leanpub.com/build-apis-you-wont-hate
42
Slide 43
Slide 43 text
Anna Filina
• Development.
• Fix bugs & performance issues.
• Workshops on testing, frameworks & APIs.
• Advisor on testing strategy, legacy code.
43