Rest Beer v2

1,269 views 40 slides Oct 04, 2015
Slide 1
Slide 1 of 40
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40

About This Presentation

Criando APIs com micro framework RESPECT e Jelastic


Slide Content

Criando APIs
usando o micro-framework
Respect

Ivan Rosolen
Graduado em Sistemas de Informação
Pós-graduado em Gerência de Projetos
Desenvolvedor a 14+ anos
Autor de vários PHPT (testes para o PHP)
Entusiasta de novas tecnologias

Head of Innovation @ Arizona
CTO @ Mokation

@ivanrosolen

API

Vantagens

- Troca de informações entre sistemas
- Múltiplas interfaces (web, mobile, CLI)
- Módulos/Componentes
- HTTP Status Codes
- Controle de Acesso


https://en.wikipedia.org/wiki/List_of_HTTP_status_codes

REST BEER

API com informações de Ceveja!
GET - http://hostname/cerveja/

POST - http://hostname/cerveja/
cerveja[nome]
cerveja[estilo]

PUT - http://hostname/cerveja/NOME
cerveja[nome]
cerveja[estilo]

DELETE - http://hostname/cerveja/NOME

RESPECT

Micro-framework para PHP 5.3+
construido por Alexandre Gaigalas
(alganet) e comunidade.

Como?

Composer

- Controle de dependências


curl -s http://getcomposer.org/installer | php
php composer.phar install



https://getcomposer.org

{
"name": "RestBeer Jelastic Demo",
"authors": [
{
"name": "Ivan Rosolen",
"email": "[email protected]"
}
],
"require": {
"respect/rest": "0.5.x",
"respect/relational": "0.5.x",
"respect/config": "0.3.x",
"respect/validation": "0.4.x"
}
}

Respect/Config


- Apenas arquivos .INI
- Usa o mesmo parser nativo e rápido do php.ini
- Extende o arquivo .INI com seu próprio “dialeto”
- Implementa lazy loading para instâncias de objeto



https://github.com/Respect/Config

db_server = "127.0.0.1"
db_name = "restbeer"
db_user = "user"
db_pwd = "pwd"
dsn_mysql = "mysql:host=[db_server];dbname=[db_name]"
<?php

use Respect\Config\Container;

// Ler arquivo de configuração
$config = new Container('config.ini');

echo $config->dsn_mysql; // mysql:host=127.0.0.1;dbname=restbeer

Respect/Relational


- Quase zero de configuracão (convenção)
- Fluent interface: $mapper->author[7]->fetch();
- Diferentes tipos de banco de dados
- Registros são tratados como Plain Data Object



https://github.com/Respect/Relational

<?php
use Respect\Relational\Mapper;

// criar instância PDO com o banco
$mapper = new Mapper(new PDO('seudsn'));

// buscar todos os autores
$authors = $mapper->author->fetchAll();

// criar objeto de um registro
$obj = new stdClass;
$obj->name = 'Ivan Rosolen';

// "gravar" informação no banco
$mapper->author->persist($obj);
$mapper->flush();

Respect/Validation


- Fluent/Chained interface: v::numeric()->positive()->between(1,
256)->validate($num)
- 100+ validadores testados
- Fácil extender ou criar novas regras (Concrete API)
- Php 7 ( Quase pronto )

https://github.com/Respect/Validation

use Respect\Validation\Validator as v;

// validar número simples
v::numeric()->validate(42); //true

// validar em cadeia
$v = v::arr() // validar se é array
->key('nome', $rule = v::alnum()->notEmpty()->noWhitespace()) // validar a key 'nome'
->key('estilo', $rule) // utilizando a mesma regra da key de cima
->validate($_POST['cerveja']);

// negação de qualquer regra
$v = v::not(v::int())->validate(10); // false

// operadores lógicos
v::allOf(v::numeric(), v::hexa(), v::min(1)); // numeric, hexadecimal e pelo menos 1
v::oneOf(v::nullValue(), v::numeric()); // null ou numeric

Respect/Router


- Thin and lightweight controller para aplicações
RESTful e APIs

- “Don't try to change PHP, small learning curve.”
- If/Before/After/Accept/Auth/Any/By …


https://github.com/Respect/Rest

<?php
use Respect\Rest\Router;

// Criar instância do router
$router = new Router; // raiz http://example.com/

// instância para trabalhar em uma subpasta
$router = new Router('/pasta'); // raiz http://example.com/pasta

// Olá mundo
$router->get('/', function() {
return 'Hello World';
});

// Separando regras das rotas :D
$router->get('/api/uri/*/*', 'Namespace\Cool\Class');
$router->post('/api/uri/', 'Namespace\Cool\Class');
$router->put('/api/uri/', 'Namespace\Cool\Class');
$router->delete('/api/uri/*', 'Namespace\Cool\Class');

Projeto

<?php
require_once realpath(__DIR__ . '/vendor/autoload.php');
use Respect\Rest\Router;
use Respect\Config\Container;
use Respect\Validation\Validator as v;
use Respect\Relational\Mapper;

//Ler arquivo de configuração
$config = new Container('config.ini');

// Criar instância PDO com o SQLite usando as configs
$mapper = new Mapper(new PDO($config->dsn_sqlite));

// Criar instância do router
$router = new Router();

//Rota para qualquer tipo de request (any)
$router->any('/', function () {
return 'RestBeer!';
});

GET Cerveja

$router->get('/cerveja/*', function ($data = null) use ($mapper) {

if ( !isset($data) ) {
$cervejas = $mapper->cervejas->fetchAll();
header('HTTP/1.1 200 Ok');
return $cervejas;
}

$data = filter_var( $data, FILTER_SANITIZE_FULL_SPECIAL_CHARS );
if ( v::not(v::alnum()->notEmpty())->validate($data) ) {
header('HTTP/1.1 400 Bad Request');
return 'Faltam parâmetros';
}

$cerveja = $mapper->cervejas(array( 'nome' => $data ))->fetch();
if ( !$cerveja ) {
header('HTTP/1.1 204 No Content');
return;
}

header('HTTP/1.1 200 Ok');
return $cerveja;
});

POST Cerveja

$router->post('/cerveja', function () use ($mapper) {

if ( !isset($_POST) || !isset($_POST['cerveja']) || v::not(v::arr())->validate($_POST['cerveja']) ) {
header('HTTP/1.1 400 Bad Request');
return 'Faltam parâmetros';
}

$valid = v::arr()->key('nome', $rule = v::alnum()->noWhitespace())->key('estilo', $rule)->validate($_POST['cerveja']);
if ( !$valid ) {
header('HTTP/1.1 400 Bad Request');
return 'Faltam parâmetros';
}

$cerveja = new stdClass();
$cerveja->nome = filter_var($_POST['cerveja']['nome'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$cerveja->estilo = filter_var($_POST['cerveja']['estilo'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);

$check = $mapper->cervejas(array( 'nome' => $cerveja->nome ))->fetch();
if ( $check ) {
header('HTTP/1.1 409 Conflict');
return 'Cerveja já existe no sistema';
}

$mapper->cervejas->persist($cerveja);
$mapper->flush();

if ( !isset($cerveja->id) || empty($cerveja->id) ) {
header('HTTP/1.1 422 Unprocessable Entity');
return 'Erro ao inserir cerveja';
}

header('HTTP/1.1 201 Created');
return 'Cerveja criada';
});

PUT Cerveja

$router->put('/cerveja/*', function ($nome) use ($mapper) {

parse_str(file_get_contents('php://input'), $data);

if ( !isset($data) || !isset($data['cerveja']) || v::not(v::arr())->validate($data['cerveja']) )
{
header('HTTP/1.1 400 Bad Request');
return 'Faltam parâmetros';
}

$nome = filter_var( $nome, FILTER_SANITIZE_FULL_SPECIAL_CHARS );
if ( v::not(v::alnum()->notEmpty())->validate($nome) ) {
header('HTTP/1.1 400 Bad Request');
return 'Faltam parâmetros';
}

$cerveja = $mapper->cervejas(array( 'nome' => $nome ))->fetch();
if ( !$cerveja ) {
header('HTTP/1.1 204 No Content');
return;
}

$newNome = filter_var( $data['cerveja']['nome'], FILTER_SANITIZE_FULL_SPECIAL_CHARS );
$newEstilo = filter_var( $data['cerveja']['estilo'], FILTER_SANITIZE_FULL_SPECIAL_CHARS );

$cerveja->nome = $newNome;
$cerveja->estilo = $newEstilo;
$mapper->cervejas->persist($cerveja);
$mapper->flush();

header('HTTP/1.1 200 Ok');
return 'Cerveja atualizada';
}); * removido parte do código para ficar melhor no slide

DELETE Cerveja

$router->delete('/cerveja/*', function ($nome) use ($mapper) {

$nome = filter_var( $nome, FILTER_SANITIZE_FULL_SPECIAL_CHARS );

if ( !isset($nome) || v::not(v::alnum()->notEmpty())->validate($nome) ) {
header('HTTP/1.1 400 Bad Request');
return 'Faltam parâmetros';
}

$cerveja = $mapper->cervejas(array( 'nome' => $nome ))->fetch();
if ( !$cerveja ) {
header('HTTP/1.1 422 Unprocessable Entity');
return 'Erro ao validar cerveja';
}

$mapper->cervejas->remove($cerveja);
$mapper->flush();

header('HTTP/1.1 200 Ok');
return 'Cerveja removida';
});

Formatar Resultado

<?php

$jsonRender = function ($data) {
header('Content-Type: application/json');
if ( v::string()->validate($data) ) {
$data = array($data);
}
return json_encode($data,true);
};

$router->always('Accept', array('application/json' => $jsonRender));

Basic Auth

<?php

// do not use this!
function checkLogin($user, $pass) {
return $user === 'admin' && $pass === 'admin';
}

$router->get('/admin', function () {
return 'RestBeer Admin Protected!';
})->authBasic('Secret Area', function ($user, $pass) {
return checkLogin($user, $pass);
});

Deploy

Jelastic


- Locaweb?
- Git
- Barato
- 14 Dias Grátis


Aplicações PHP no Jelastic https://t.co/aHi3ZixLon

Referências / Links

Github
https://github.com/ivanrosolen/RestBeer-Jelastic

Respect
http://respect.github.io

Jelastic
http://www.locaweb.com.br/cloud/jelastic
https://twitter.com/kemelzaidan
http://pt.slideshare.net/ivanrosolen/jelastic-53375753

PHPSP
http://phpsp.org.br

Elton Minetto
https://github.com/eminetto/restbeer

Dúvidas?

OBRIGADO!



Avalie esta palestra
joind.in/15207

Visite phpsp.org.br