Criando APIs
usando o micro-framework
        Silex
Elton Minetto
              Graduado/pós-graduado em Ciência da Computação
                        Desenvolvedor desde 1997
                           Professor desde 2004
                       Autor de dois livros sobre PHP


Sócio da   Coderockr
                                 Instrutor do   Code Squad
API
O que é?
"[] conjunto de rotinas e padrões estabelecidos por um
software para a utilização das suas funcionalidades por
aplicativos que não pretendem envolver-se em detalhes
da implementação do software, mas apenas usar seus
serviços []"
                                               Wikipedia
Porque criar uma
     API?
Múltiplas interfaces (web, mobile, CLI)
Integração com outros serviços da sua
              empresa
 Venda de recursos (Amazon, Parse, Pusher,
               Filepicker, etc)
Exemplo
RestBeer
API de informações sobre cerveja
       http://restbeer.com/cervejas/
        http://restbeer.com/estilos/
  http://restbeer.com/cervejas/Guinness
  http://restbeer.com/cervejas/Heineken
    http://restbeer.com/estilos/Pilsen
    http://restbeer.com/estilos/Stout
Silex
Micro-framework para PHP 5.3 (e
superiores) construído com base nos
componentes do Symfony e inspirado no
Sinatra (ruby)
Instalando
Criando o composer.json
{
    "require": {
        "silex/silex": "1.0.*"
    },
    "minimum-stability": "dev"
}




Instalando as dependências
curl -s http://getcomposer.org/installer | php
php composer.phar install
Mostrando as
  cervejas
<?php
use SilexApplication;

//loader do Composer
$loader = require_once __DIR__.'/vendor/autoload.php';

$app = new Application();

$cervejas = array(
    'marcas' => array('Heineken', 'Guinness', 'Skol', 'Colorado'),
    'estilos' => array('Pilsen' , 'Stout')
);

$app->get('/cervejas', function () use ($cervejas) {
    return implode(',', $cervejas['marcas']);
});

$app->get('/estilos', function () use ($cervejas) {
    return implode(',', $cervejas['estilos']);
});
$app->run();
Testando com o
servidor do PHP 5.4
php -S localhost:8080
Mostrando uma em
   específico
$app->get('/cervejas/{id}', function ($id) use ($cervejas) {
    if ($id == null) {
       return implode(',', $cervejas['marcas']);
    }

    $key = array_search($id, $cervejas['marcas']);
    if ($key === null) {
        return 'Não encontrada';
    }
    return $cervejas['marcas'][$key];
})->value('id', null);
Formatando o
  resultado
//Adicionar os novos namespaces no começo do arquivo
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentHttpFoundationRequest;
...
//alterar o /cervejas
$app->get('/cervejas/{id}', function ($id) use ($cervejas) {
    if ($id == null) {
        $result = implode(',', $cervejas['marcas']);
        return new Response (json_encode($result), 200);
    }
    $key = array_search($id, $cervejas['marcas']);
    if ($key === null) {
        return new Response (json_encode('Não encontrada'), 404);
    }
    return new Response (json_encode($cervejas['marcas'][$key]),
200);
})->value('id', null);

//adiciona o cabeçalho após todas as requisições
$app->after(function (Request $request, Response $response) {
    $response->headers->set('Content-Type', 'text/json');
});
Autenticando
$app->before(function (Request $request) use ($app) {
    if( ! $request->headers->has('authorization')){
        return new Response('Unauthorized', 401);
    }

    require_once 'configs/clients.php';
    if (!in_array($request->headers->get('authorization'),
array_keys($clients))) {
        return new Response('Unauthorized', 401);
    }
});
Adicionando uma
     Cerveja
$app->post('/cervejas', function (Request $request) use ($app) {
    //pega os dados
    if (!$data = $request->get('cerveja')) {
        return new Response('Faltam parâmetros', 400);
    }

    //Persiste na base de dados (considerando uma entidade do
Doctrine nesse exemplo)
    $cerveja = new Cerveja();
    $cerveja->nome = $data['nome'];
    $cerveja->estilo = $data['estilo'];
    $cerveja->save();

      //redireciona para a nova cerveja
      return $app->redirect('/cervejas/' . $data['nome'], 201);
});
Alterando uma
    Cerveja
$app->put('/cervejas/{id}', function (Request $request, $id) use
($app) {
    //pega os dados
    if (!$data = $request->get('cerveja')) {
         return new Response('Faltam parâmetros', 400);
    }
    //busca da base de dados
    if (!$cerveja = $app['db']->find($id)) {
         return new Response('Não encontrada', 404);
    }
    //Persiste na base de dados
    $cerveja->nome = $data['nome'];
    $cerveja->estilo = $data['estilo'];
    $cerveja->save();

      return new Response('Cerveja atualizada', 200);
});
Excluindo uma
   Cerveja
$app->delete('/cervejas/{id}', function (Request $request, $id) use
($app) {
   //busca da base de dados
    if (!$cerveja = $app['db']->find($id)) {
         return new Response('Não encontrada', 404);
    }
    $cerveja->delete();

      return new Response('Cerveja removida', 200);
});
Referências
Exemplo completo
(com integração com o Docrine e usando SQLite)

    https://github.com/eminetto/restbeer
http://www.slideshare.net/hhamon/silex-meets-soap-
rest
http://www.slideshare.net/Alganet/rest-faa-o-servio-
direito
http://silex.sensiolabs.org
https://github.com/eminetto/silex-sample
https://github.com/Coderockr/SOA-Server
https://github.com/Coderockr/SOA-Client
Contato
@eminetto
http://www.eltonminetto.net
    http://coderockr.com
   http://code-squad.com

Api usando Silex