Olá pessoal, hoje veremos um exemplo de como utilizar o Slim Framework para construir uma API RESTful com PHP.
O que é RESTful
REST é a abreviação de Representation State Transfer, ou traduzindo, Transferência de Estado Representacional. Tal arquitetura tem como base três princípios: Recursos, ações e conteúdo.
Recursos
Estes são identificados na requisição, por exemplo: http://api.clubedosgeeks.com.br/usuario/jayr
Ações
São as ações definidas pelo protocolo HTTP:
Metodo | Exemplo | Descrição |
GET | //api.clubedosgeeks.com.br/usuarios | Lista todos os usuários |
GET | //api.clubedosgeeks.com.br/usuario/1 | Lista apenas usuário com id = 1 |
POST | //api.clubedosgeeks.com.br/usuarios | Para cadastrar usuários |
PUT | //api.clubedosgeeks.com.br/usuario/1 | Para editar usuários |
DELETE | //api.clubedosgeeks.com.br/usuario/1 | Para apagar usuário |
Conteúdo
MIME TYPES – Deve ser usado para determinar o tipo de conteúdo que será usado. A identificação geralmente é feita no cabeçalho pelo campo cujo o nome é Content-type. Normalmente os tipos usados são JSON e XML. No nosso exemplo usaremos JSON.
Banco de dados
Iremos usar o mysql, crie um banco de dados, e uma tabela simples para cadastro de pessoa.
CREATE DATABASE api;
CREATE TABLE pessoa ( id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, nome VARCHAR(30) NOT NULL, email VARCHAR(50), dt_cadastro DATETIME DEFAULT CURRENT_TIMESTAMP )
Slim Framework
É considerado um microframework, e tem como principal objetivo a construção de APIs. Veja o site oficial.
Instalando
Para instalar o Slim você vai precisar usar composer. Instale-o primeiro.
Crie um arquivo chamado composer.json, e escreva o seguinte nele:
{ "require": { "slim/slim": "2.*" }, "autoload": { "psr-4": { "controllers\\": "controllers" } } }
Feito isso, abra o terminal ou o Prompt de comando, vá até a pasta de sua aplicação usando cd, e execute:
$ composer install
Pronto, está instalado! Agora vamos começar nossa aplicação.
Antes, note que no composer colocamos a pasta controllers para ser inclusa na nossa aplicação via autoloader.
.htaccess
Para começar, acesse a pasta \vendor\slim\slim, e copie o arquivo .htaccess para a pasta raiz da sua aplicação.
Estrutura das pastas
Nossa API será organizada da seguinte maneira:
templates/default.php
Este arquivo, como o nome sugere, é um arquivo padrão de template, que nos servirá como view. Este arquivo deve setar os cabeçalhos e mostrar o json.
<?php header('Content-Type: application/json; charset=utf-8'); echo json_encode($data);
controllers/Pessoa.php
Neste arquivo faremos os controles das ações, listando, salvando, editando e excluindo.
Note que usei a biblioteca PDO, e em alguns pontos você pode achar que tem muito código escrito, como na função editar por exemplo. Mas você pode usar a conexão que quiser. Gosto do PDO por ser orientado a objetos. Mas fica ao seu dispor.
<?php namespace controllers{ /* Classe pessoa */ class Pessoa{ //Atributo para banco de dados private $PDO; /* __construct Conectando ao banco de dados */ function __construct(){ $this->PDO = new \PDO('mysql:host=localhost;dbname=api', 'root', ''); //Conexão $this->PDO->setAttribute( \PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION ); //habilitando erros do PDO } /* lista Listand pessoas */ public function lista(){ global $app; $sth = $this->PDO->prepare("SELECT * FROM pessoa"); $sth->execute(); $result = $sth->fetchAll(\PDO::FETCH_ASSOC); $app->render('default.php',["data"=>$result],200); } /* get param $id Pega pessoa pelo id */ public function get($id){ global $app; $sth = $this->PDO->prepare("SELECT * FROM pessoa WHERE id = :id"); $sth ->bindValue(':id',$id); $sth->execute(); $result = $sth->fetch(\PDO::FETCH_ASSOC); $app->render('default.php',["data"=>$result],200); } /* nova Cadastra pessoa */ public function nova(){ global $app; $dados = json_decode($app->request->getBody(), true); $dados = (sizeof($dados)==0)? $_POST : $dados; $keys = array_keys($dados); //Paga as chaves do array /* O uso de prepare e bindValue é importante para se evitar SQL Injection */ $sth = $this->PDO->prepare("INSERT INTO pessoa (".implode(',', $keys).") VALUES (:".implode(",:", $keys).")"); foreach ($dados as $key => $value) { $sth ->bindValue(':'.$key,$value); } $sth->execute(); //Retorna o id inserido $app->render('default.php',["data"=>['id'=>$this->PDO->lastInsertId()]],200); } /* editar param $id Editando pessoa */ public function editar($id){ global $app; $dados = json_decode($app->request->getBody(), true); $dados = (sizeof($dados)==0)? $_POST : $dados; $sets = []; foreach ($dados as $key => $VALUES) { $sets[] = $key." = :".$key; } $sth = $this->PDO->prepare("UPDATE pessoa SET ".implode(',', $sets)." WHERE id = :id"); $sth ->bindValue(':id',$id); foreach ($dados as $key => $value) { $sth ->bindValue(':'.$key,$value); } //Retorna status da edição $app->render('default.php',["data"=>['status'=>$sth->execute()==1]],200); } /* excluir param $id Excluindo pessoa */ public function excluir($id){ global $app; $sth = $this->PDO->prepare("DELETE FROM pessoa WHERE id = :id"); $sth ->bindValue(':id',$id); $app->render('default.php',["data"=>['status'=>$sth->execute()==1]],200); } } }
index.php
Na pasta raiz da aplicação teremos um arquivo chamado index.php que será o arquivo principal da aplicação.
Nele faremos nossas rotas para o(s) controller(s). Se você preferir ter um arquivo de rotas separado, basta incluir ele depois.
<?php //Autoload $loader = require 'vendor/autoload.php'; //Instanciando objeto $app = new \Slim\Slim(array( 'templates.path' => 'templates' )); //Listando todas $app->get('/pessoas/', function() use ($app){ (new \controllers\Pessoa($app))->lista(); }); //get pessoa $app->get('/pessoas/:id', function($id) use ($app){ (new \controllers\Pessoa($app))->get($id); }); //nova pessoa $app->post('/pessoas/', function() use ($app){ (new \controllers\Pessoa($app))->nova(); }); //edita pessoa $app->put('/pessoas/:id', function($id) use ($app){ (new \controllers\Pessoa($app))->editar($id); }); //apaga pessoa $app->delete('/pessoas/:id', function($id) use ($app){ (new \controllers\Pessoa($app))->excluir($id); }); //Rodando aplicação $app->run();
Pronto está pronta nossa API.
Testando
Você pode testar sua nova API usando Postman, ou outro cliente REST.
GitHub
Você pode ver este projeto no GitHub
Muito bom… Parabens pelo artigo.
todos os comandos funcionaram menos o editar (put).
talvez seje porque usando no windows.
Opa Jose, eu fiz esse post usando Windows. Dá algum erro quando você chama o PUT?
Tive o mesmo problema, meu PUT não consegue rodar o json decode, retornando o array sempre vazio, apenas o POST e GET funcionaram ;/
como ficaria esse exemplo com autenticação?
Cara, depende de como você quer usar autenticação. Por token ou seção. Você só precisa usar um middleware do Slim para testar se existe a seção ou o token.
Parabéns pelo post.
Funcionou tudo perfeito.
Gostaria de fazer uma pergunta. Se tratando de uma API grande. Os cadastros, as alterações e as exclusões não são feitas em blocos? Como funcionaria essa parte se eu tivesse um array de objetos para realizar essas operações?
Você teria que tratar o array no Controller.
Muito útil esse tutorial!
Fiquei apenas com uma dúvida, no caso da consulta, teria como passar dois parâmetos ao invés de mandar somente o ID ?
Sim, só colocar a outra variável. Tipo:
$app->get(‘/pessoas/:id/:outro’, function($id, $outro) use ($app){
(new \controllers\Pessoa($app))->get($id);
});
Parabéns pelo seu trabalho, consegui usá-lo e a sua abordagem é bem legal. Vi que a versão da Slim é 2.6 para este exemplo, teria como você atualizar para 3.0, pois teve muitos métodos que mudaram ?
Parabéns brother, muito bem explicado. Me ajudou bastante aqui 🙂
Parabéns pelo seu trabalho ficou muito bom e fácil de entender. Preciso fazer um trabalho na faculdade usando a linguagem php, como sou iniciante não estou conseguido configurar o CORS. Pode me ajudar ?
Boa noite, era o que eu precisava.
Sou novo em php, para colocar isto nas nuvens, o processo e igual ao colocar uma pagina ou tem algum segredinho a mais?
Obrigado
Muito bom e muito util, mas fiquei na duvida de como eu passaria um filtro na função lista(), para obter os dados filtrados
Boa tarde,
como faço para retornar os códigos de resposta http (ex. 200, 401)?
Tem como atualizar para Slim 3?
Acredito que seja apenas necessário vc concatenar com sua Consulta SQL
Tentei fazer mas nao deu certo, fiz ate um git clone também não funcionou deu 404,
http://localhost/api-php-slim-framework/pessoas/. Alguém poderia me ajudar aonde estou errando.
Olá.
Excelente o seu post. Testei aqui e funcionou perfeitamente.
A minha dúvida é:
Eu poderia passar o nome do controller dinamicamente?
$app->post(‘/pessoas/’, function() use ($app){
(new \controllers\Pessoa($app))->nova();
});
no caso, passar dinamicamente o ‘/pessoas/’ eu consigo, mas o \controllers\Pessoa eu não consegui fazer.
tem uma dica?
Não estou conseguindo testar, poderia me auxiliar, grato
Qual é sua dificuldade?