API RESTful com PHP e Slim Framework

PHP

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:

ac.fw

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

 

Jayr Alencar

Doutorando em Ciências da Computação no Centro de Informática da Universidade Federal do Pernambuco (CIn - UFPE); Mestre pela mesma instituição; Formado em Análise e Desenvolvimento de Sistemas; Católico; Fã de O Senhor do Anéis.

23 thoughts on “API RESTful com PHP e Slim Framework

      1. Tive o mesmo problema, meu PUT não consegue rodar o json decode, retornando o array sempre vazio, apenas o POST e GET funcionaram ;/

  1. 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?

  2. 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 ?

  3. 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 ?

  4. 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 ?

  5. 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

  6. Muito bom e muito util, mas fiquei na duvida de como eu passaria um filtro na função lista(), para obter os dados filtrados

  7. 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?

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *


Deprecated: Creation of dynamic property Daisy_Blog_Google_Local::$files is deprecated in /home2/clube692/public_html/wp-content/themes/daisy-blog/inc/blocks/font-family/inc/class-fonts-google-local.php on line 77

Deprecated: Creation of dynamic property Daisy_Blog_Google_Local::$files is deprecated in /home2/clube692/public_html/wp-content/themes/daisy-blog/inc/blocks/font-family/inc/class-fonts-google-local.php on line 77