Thiago Cantero

Tecnologia e Entretenimento

Desenvolvimento WebLaravelPHP

API Restful, conceitos e exemplo prático.

Olá, mundo!Tudo bem?

Nos dias atuais existem uma enxurrada de informações, vídeos, até mesmo cursos voltados para este conceito. Que nada mais é de uma forma de comunicação, nada moderna, já idealizada com o Modelo OSI (Open System Interconnection) em 1971.

Afinal, o que é uma API (Application Programming Interface) e o termo Restful? Vejamos a tabela do modelo proposto pelo Modelo OSI:

CAMADA FUNÇÃO
7 – Aplicação Funções especialistas (transferência de arquivos, envio de e-mail, terminal virtual).
6 – Apresentação Formatação dos dados, conversão de códigos e caracteres (compressão e criptografia).
5 – Sessão Negociação e conexão com outros nós, analogia.
4 – Transporte Oferece métodos para a entrega de dados ponto-a-ponto.
3 – Rede Roteamento de pacotes em uma ou várias redes.
2 – Enlace Detecção de erros.
1 – Física Transmissão e recepção dos bits brutos através do meio físico de transmissão.

Fonte: Tabela obtida no Wikipedia, acesso em https://pt.wikipedia.org/wiki/Modelo_OSI .

Quando falamos sobre API, nos remete a interoperabilidade, ou seja, queremos que Sistemas de linguagens, Sistema Operacionais distintos, até mesmo Banco de Dados e/ou informações, cuja as fontes de dados são divergentes, tenham a devida comunicação. Esta é a real importância e significado de uma API. Não é raro vermos Sistemas em que você realiza a pesquisa de um CEP e retorna, de maneira automática, o preenchimento de seu endereço. Esta função é exercida com o uso de uma API.

E o que seria o Restful?A comunicação em Sistema Web se faz através da representatividade de estado (REST – Representational state transfer), calma! Eu explico, sem melindres e charlatanismo!

Toda requisição Web se faz através de protocolo, correto?Para tal, utilizamos o protocolo HTTP. (Tá bom, vão falar que usam o HTTPS, que apenas tem uma funcionalidade de proteger o cabeçalho, o payload da mensagem com segurança). Desfeito estes mitos, vamos em frente!

Utilizamos os verbos: GET, PUT, POST, PATCH, DELETE, HEAD, nossa aplicação de exemplo, será uma base de cliente, e fará o famoso CRUD (Create, Read, Update e Delete), em português: Criação, Leitura, Atualização e Apagar. Munido destes preceitos básicos, vejamos abaixo os verbos HTTP, especificado e suas respectivas funções na aplicação:

 

VERBO
HTTP
CRUD
ENDPOINTS (/cLIENTEs)
POST Create Nosso endpoint direcionará no Controller Clientes /clientes o qual irá gerar um novo registro
GET Read Neste endpoint iremos pegar uma coleção completa com o método All() do Eloquent e também um outro endpoint /clientes/{id}, que retornará o registro que quisermos filtrar, baseando-se na chave primária do registro.
PUT Update Este endpoint terá a incumbência de alterar o registro, baseado na rota /clientes/{id}
DELETE Delete Este endpoint apagará o registro no banco, baseado na rota /clientes/{id}

Vamos dar início aos trabalhos, criando uma aplicação Laravel! ; )

composer create-project laravel/laravel laravel_api

entramos na pasta do projeto /laravel_api

criamos nosso banco de Dados:

mysql -u root -p

CREATE DATABASE laravel_api;

Voltamos para nossa pasta do projeto e façamos a edição do arquivo .env do Laravel.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_api
DB_USERNAME=root
DB_PASSWORD=<senha do banco de dados>

Vamos criar a classe de Modelo e com a flag -m para a criação da migração para o banco de dados.

php artisan make:model Cliente -m

Vamos até a pasta /app/Models/Cliente.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Cliente extends Model
{
    protected $table = 'clientes';

    protected $fillable  = ['nome', 'telefone'];

}

Agora iremos alterar nossa migração na pasta /laravel_api/database/migrations/2022_06_30_170531_create_clientes_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateClientesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('clientes', function (Blueprint $table) {
            $table->id();
            $table->string('nome');
            $table->integer('telefone');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('clientes');
    }
}

Vamos rodar a migração para criação da tabela no banco de dados:

php artisan migrate

Com o banco devidamente criado, vamos agora criar o Controller que atenderá as requisições.

php artisan make:controller ClientesApiController

 

Vamos incluir os seguintes métodos em nosso Controller, vamos até a pasta /laravel_api/app/Http/Controllers/ClientesApiController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Cliente;


class ClientesApiController extends Controller
{
    public function getAllClientes() {
        // iremos pegar a coleção de todos os clientes aqui
        $clientes = Cliente::get()->toJson(JSON_PRETTY_PRINT);
        return response($clientes, 200);
      }
  
      public function createCliente(Request $request) {
        // Criação do Cliente com Active Record Pattern
        $cliente = new Cliente;
        $cliente->nome = $request->nome;
        $cliente->telefone = $request->telefone;
        $cliente->save();

        //Retorna em JSON a resposta e a mensagem de "Registro de cliente criado"
        return response()->json([
            "mensagem" => "Registro de Cliente criado"
        ], 201);
      }
  
      public function getCliente($id) {
        // Verifica se o registro existe, caso exista, pega a coleção e tranforma em JSON, caso não encontre
        // retorna com "Cliente não encontrado!"
        if (Cliente::where('id', $id)->exists()) {
            $cliente = Cliente::where('id', $id)->get()->toJson(JSON_PRETTY_PRINT);
            return response($cliente, 200);
          } else {
            return response()->json([
              "mensagem" => "Cliente não encontrado!"
            ], 404);
          }
      }
      
  
      public function updateCliente(Request $request, $id) {
        // Verifica se o cliente existe, caso exista pega as informações, trata se for valor nulo com o ternário (ambos os valores cliente,telefone)
        // ao final salva com o método Active Record Pattern e mostra a mensagem "Registros atualizados com sucesso!"
        // Caso não há registro retorna a mensagem "Cliente não encontrado!"
        if (Cliente::where('id', $id)->exists()) {
            $cliente = Cliente::find($id);
            $cliente->nome = is_null($request->nome) ? $cliente->nome : $request->nome;
            $cliente->telefone = is_null($request->telefone) ? $cliente->telefone : $request->telefone;
            $cliente->save();
    
            return response()->json([
                "mensagem" => "Registros atualizados com sucesso!"
            ], 200);
            } else {
            return response()->json([
                "mensagem" => "Cliente não encontrado!"
            ], 404);
            
        }
      }
  
      public function deleteCliente ($id) {
        // método para apagar um cliente, verifica se o registro existe. Caso exista efetua a remoção com método delete().
        // Caso não exista, retorna a mensagem "Cliente não encontrado!"
        if(Cliente::where('id', $id)->exists()) {
            $cliente = Cliente::find($id);
            $cliente->delete();
    
            return response()->json([
              "mensagem" => "Registros apagados!"
            ], 202);
          } else {
            return response()->json([
              "mensagem" => "Cliente não encontrado!"
            ], 404);
          }
        
      }
}

Agora vamos colocar no arquivo de rotas do Laravel, nossas endpoints que iremos consumir. /laravel_api/routes/api.php

<?php

use App\Http\Controllers\ClientesApiController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});


Route::get('clientes', [ClientesApiController::class, 'getAllClientes']);
Route::get('clientes/{id}',  [ClientesApiController::class, 'getCliente']);
Route::post('clientes', [ClientesApiController::class],'createCliente');
Route::put('clientes/{id}', [ClientesApiController::class],'updateCliente');
Route::delete('clientes/{id}', [ClientesApiController::class, 'deleteCliente']);

 

Antes de testar nossa aplicação, vamos criar alguns clientes para nossa base experimental:

php artisan make:seed ClienteSeeder

 

Vamos até a pasta de nossa Seeder criada /laravel_api/database/seeders/ClienteSeeder.php

<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\Cliente;

class ClienteSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $clientes = [ ["nome" => "Thiago Cantero",
                      "telefone" => "1199999999"], 
                      ["nome" => "Mario Bros",
                      "telefone" => "1122222222"],
                      ["nome" => "ElePHant",
                      "telefone" => "11233232"],
                      ["nome" => "Yoshi",
                      "telefone" => "11222212"]          
                ];

                foreach ($clientes as $key => $value) { 
                    Cliente::create($value);        
                    }
    }
}

agora vamos executar o comando para popular nossa seeder no banco:

php artisan db:seed --class=ClienteSeeder

Os dados estão na base:

Por fim, vamos testar nossa aplicação. No meu ambiente utilizo o insomnia

Façamos o comando:

php artisan serve

Abrimos o Isomnia, e façamos a rota de acesso a coleção, que em nosso Controller está no método getAllClientes().

Nossa API já está funcionando, ela retorna toda as coleções que fizemos na seed. Vamos pegar um registro apenas, informando o id “4”, este método é o getCliente() de nosso Controller.

 

Pegamos o registro Yoshi do nosso banco de dados.

Agora vamos apagar o primeiro registro de nossa base de dados. No caso o Id “1”. Que chamará o método deleteCliente() de nosso Controller.

Façamos o chamado de todas nossa coleções novamente.

Perfeito, nossa API está funcional e pronta para ser consumida. É óbvio que este exemplo tem apenas o intuito de demonstrar para que serve uma API e o tais termos REST e RESTFul.
Espero que tenha ajudado.

Código fonte no github.

 

Sofrer, é só uma vez; vencer, é para a eternidade.