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 by IDs and apply sorting.
13
Slide 14
Slide 14 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.
• Look under $_FILES.
14
Slide 15
Slide 15 text
Plupload
var uploader = new plupload.Uploader({
runtimes: 'html5,html4',
max_file_size: '5mb',
url: '/api/upload',
filters: [{extensions: 'jpg,png,jpeg'}]
});
uploader.init();
15
Status codes
• Don't confuse API & HTTP codes.
• 2xx success
• 3xx redirect
• 4xx client error
• 5xx server error
• Send API-specific code in body.
17
Slide 18
Slide 18 text
Example of error
Status: 400
Content-Type: application/json; charset=UTF-8
{
"error": {
"code": 1001,
"message": "Price must be greater than 0."
}
}
18
Slide 19
Slide 19 text
Testing
Simpler than you think.
Slide 20
Slide 20 text
HTTP
• Use Guzzle or built-in framework tool.
• Generate HTTP request , compare output.
20
Testing tips
• Create separate database for tests.
• Write tests before you code:
• TDD
• Contract between you and frontend dev.
22
Slide 23
Slide 23 text
Authentication
Nooo, I hate that part! Someone else code it plz.
Slide 24
Slide 24 text
Multiple methods
• You can have multiple auth methods for one API.
• Session can be one of them if same app.
24
Slide 25
Slide 25 text
OAuth2
• SSL required.
• Advanced features like access scope.
• More security: use authorization server.
25
Slide 26
Slide 26 text
OAuth2 - Step 1 (simplified approach)
26
Login
User Client app
(php/js/mobile)
Forward
API
Validate
Create
token
Store
token
user/pass user/pass
token
Slide 27
Slide 27 text
OAuth2 - Step 2
27
Fetch
Display
page
Done
token
data
page
Access
page
Request
data
Validate
token
User Client app
(php/js/mobile)
API
Authorization: Bearer zaVOP1lmQja4Lz-^RLwvzapvjd
Slide 28
Slide 28 text
OAuth2 - Auth server
28
User Client app
(php/js/mobile)
API
Auth
Request Forward
Validate
Create
token
Store
token
token
Login form
Login
Store
token
token
user/pass
Slide 29
Slide 29 text
Refactoring to API
Don't rewrite all the legacy at once.
Slide 30
Slide 30 text
Micro-services
30
Products Orders Inventory
/categories
/products
/reviews
/customers
/orders /warehouses
/sales-reps
get info
update
stock
get info
Slide 31
Slide 31 text
Progressive rewrite
• Rewrite one component at a time.
• Start with whatever has fewer dependencies (or critical).
• Will have duplicate functionality for a time.
○ Example: orders will still fetch products the old way.
• Copy production data for dev environment.
31
Slide 32
Slide 32 text
Services vs libraries
• Services: GET /products?id=1,5
• Libraries:
• $db->getList( ["id" => "1,5"] );
• Can fetch without pagination.
• Can hydrate to models.
• Bypass HTTP.
32
Slide 33
Slide 33 text
Implementation tips
Is this a good way to code it?
Slide 34
Slide 34 text
Libraries
• I use Symfony & Doctrine.
• Aside from frameworks, I prefer small tools that don't do
too much magic.
• OptionsResolver component to validate parameters.
• Validator to validate entities (models).
34
Validator
$validator = Validation::createValidator();
$constraint = new Assert\Collection([
'name' => new Assert\Length(['min'=>2]),
'photos' => new Assert\Collection([
'file' => new Assert\Image(),
]),
]);
$violations = $validator->validateValue($input,
$constraint);
36
Slide 37
Slide 37 text
Validator
• Can read constraints from model annotations.
/** @Assert\ Length(min=5, minMessage="Too short") **/
• List of violations for you to forward to client.
• Can validate files, emails, IPs, credit cards, dates, etc.
37
Slide 38
Slide 38 text
Reuse & standardize
• Goal: streamline endpoint creation.
• Base controller for common request processing.
• Base repository for querying with filters.
• Keep things fully customizable.
◦ Not too much magic.
◦ I avoid out-of-the-box solutions.
38
Slide 39
Slide 39 text
Performance
Make things faster. Much faster.
Slide 40
Slide 40 text
Benchmark
• Make performance part of your test suite.
• Give Blackfire a spin.
• In dev/test mode, use a meta block (or add to headers).
40
Perfomance 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).
42
Slide 43
Slide 43 text
Useful links
• Standard API format
http://jsonapi.org/format/
• Blackfire
https://blackfire.io
• OAuth2
http://oauth2.thephpleague.com/
• OAuth2 with mobile
http://www.slideshare.net/briandavidcampbell/...
• 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
43
Slide 44
Slide 44 text
Anna Filina
• @afilina
• afilina.com
• Development: PHP, JS, etc.
• Fix problems: bugs, performance, etc.
• Workshops: testing, Symfony, AngularJS, API, etc.
• Advisor: testing strategy, legacy code, etc.
44