Thiago Cantero

Tecnologia e Entretenimento

APILaravelObserverPadrões de ProjetoPHPProgramação

API de pesquisa de CEP em Laravel

Ola, mundo! Tudo bem?

Neste artigo demonstrarei o conceito aplicado, que expus em um artigo anterior que trata sobre API (aqui), com os conceitos bem reforçados em mente, demonstrarei na práxis (prática : ) ) o funcionamento de uma API que retorna, através de uma consulta pelo CEP, o logradouro.

Mas antes de começarmos o trabalho, vou expor alguns outros conceitos que também servirão de ajuda a quem possui alguma dúvida. Se você leu o artigo que destaquei no link acima, deve se lembrar do Modelo OSI, este que tem a premissa de normatizar a interoperabilidade de Sistemas distintos com o objetivo de eles terem total interatividade, isto no conceito dos primórdios das redes…

Bom, para que se tenha uma forma de comunicação necessitamos para tanto de um meio, este caro leitor é o ponto inicial de toda e qualquer maneira de se expressar. Em nosso exemplo, nos valeremos do padrão IEEE 802, que já tem seus 40 anos, muito bem vividos, eu diria! ; )

Como sempre, gosto de referenciar grandes autores que me influenciam até os dias de hoje, vejamos o Brilhante Tanenbaum:

Existe na literatura uma considerável confusão entre uma rede de computadores e um sistema distribuído. A principal diferença entre eles é que, em um sistema distribuído, um conjunto de computadores independentes parece ser, para usuários, um único sistema coerente. Em geral, ele tem um único modelo ou paradigma que apresenta aos usuários. Com freqüência, uma camada de software sobre o sistema operacional, chamada middleware, é responsável pela implementação desse modelo. Um exemplo bem conhecido de sistema distribuído é a World Wide Web, na qual tudo tem a aparência de um documento (uma página da Web).
Em uma rede de computadores, essa coerência, esse modelo e esse software estão ausentes. Os usuários ficam expostos às máquinas reais, sem qualquer tentativa por parte do sistema de fazer as máquinas parecerem e atuarem de modo coerente. Se as máquinas tiverem hardware diferente e sistemas operacionais distintos, isso será totalmente visível para os usuários. Se quiser executar um programa em uma máquina remota, o usuário terá de efetuar o logon nessa máquina e executar o programa lá.
Na prática, um sistema distribuído é um sistema de software instalado em uma rede. O software dá ao sistema um alto grau de coesão e transparência. Conseqüentemente, é o software (e em particular o sistema operacional) que determina a diferença entre uma rede e um sistema distribuído, não o hardware. Redes de Computadores, Andrew S. Tanembaum, 4ª Edição (2003), pág. 18-19 Editora Elsevier.

Mesmo que a excelente obra do Mestre Tanembaum, os conceitos são perfeitamente adequados e aplicados nos dias atuais.

Caso se interesse, você pode adquirir a Obra, na Edição mais atual “Redes de Computadores – 6ª Edição – Andrew S. Tanembaum“.

Bom, com as definições muito bem explanadas e referenciadas, vamos ao nosso problema, que terá solução, fiquem tranquilos. Mas antes, quero deixar claro que para a criação de uma API, devemos atender alguns requisitos, como versionamentos dela, segurança através de tokens, dentre outras boas práticas atinentes a implementação desta.

E nesta dialética do teórico/prático (práxis), vamos ao projeto!

Vamos ao Trabalho\\

Nossa API deverá retornar uma coleção em JSON similar a esta estrutura:

[
  {
    "cep": "01007000",
    "logradouro": "Rua Riachuelo",
    "complemento": "",
    "bairro": "Sé",
    "localidade": "São Paulo",
    "uf": "SP",
    "ibge": 3550308
  }
]

Em que temos os seguintes valores, o CEP com valor em (String), logradouro (String), complemento (String), bairro (String), localidade (String), uf (String), ibge (Inteiro). Esta coleção consumiremos em alguma aplicação de cadastro de cliente/entrega, etc.

Aviso Importante

A Base de Dados aqui não tem nenhuma relação a pessoa, apenas os endereços em si, não infringindo a Lei Geral de Proteção de Dados, que visa a proteção das informações do Indivíduo/Segurança do Estado. Vez que os dados de endereços são amplamente buscados/acessados em fontes abertas da internet.

Iniciamos nosso projeto:

composer create-project laravel/laravel api_cep

Na pasta de nosso projeto vamos criar nossa Classe Model e com a flag -m, vamos criar também nossa migration:

php artisan make:model Cep -m

Nossa Migration:

database/migrations/2022_08_01_120405_create_ceps_table.php

<?php

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

class CreateCepsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('cep', function (Blueprint $table) {
            $table->id();
            $table->string('cep');
            $table->string('logradouro');
            $table->string('complemento');
            $table->string('bairro');
            $table->string('localidade');
            $table->string('uf');
            $table->integer('ibge');
            $table->timestamps();
        });
    }

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

Nossa Model:

app/Models/Cep.php

<?php

namespace App\Models;

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

class Cep extends Model
{
    protected $table = 'cep';
    protected $fillable = ['cep', 'logradouro', 'complemento', 'bairro', 'localidade', 'uf'];
    
}

vamos configura nosso arquivo de ambiente .env na raiz do projeto para termos acesso ao banco de dados:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=<usuário do banco de dados>
DB_PASSWORD=<senha do banco de dados>

vamos criar nosso banco de dados:

create database cep;

 

Agora vamos rodar nossa migration:

php artisan migrate

Agora vou fazer o processo de carga na base de dados de CEP, eu deixarei disponibilizado em formato SQL99 para que você possa fazer o mesmo. Você pode usar até o mesmo alguma aplicação de sua linguagem favorita para fazer o parser do arquivo e, através de filas, efetuar a carga, para que sua infraestrutura não sofra demasiadamente. Eu aconselho uma ferramenta de ETL, eu gosto muito da Pentaho Data Integration, ou se preferir o que expus a pouco. Isso vai de sua escolha! ; )

Antes de efetuar carga, vamos fazer uma alteração de constraint em nossa tabela (poderíamos ter feito isso na migration), no entanto o exemplo é para fins didáticos” ; )

ALTER TABLE `cep` CHANGE `logradouro` `logradouro` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, CHANGE `complemento` `complemento` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, CHANGE `bairro` `bairro` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, CHANGE `ibge` `ibge` INT(11) NULL;

Efetue a carga:

Vamos consultar o banco para verificar os registros:

Retornaram 732763 linhas de registros, não é a base mais completa, no entanto já ajuda muito para uma solução local.

Agora precisamos criar nosso Controller, que servirá de nos prover o verbo GET e, consequentemente, ofertar nossa pesquisa em JSON.

php artisan make:controller /Api/CepAPI

Vamos editar nosso Controller:

app/Http/Controllers/Api/CepAPI.php

<?php
/**   
 * API de Conculta de CEP Base 2018 
 * @version 1.0   
 * @package CEP
 * @subpackage Controller API
 * @author Thiago Cantero Mari Monteiro   
 * @copyright Copyright (c) 2022 Thiago Cantero Mari Monteiro   
 * @license http://www.thiagocantero.com.br/sobre  
 **/


namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Cep;


class CepAPI extends Controller
{
  
    public function getCEP($cep){
  
      
      if (Cep::where('cep', $cep)->exists()){
          $CEP = Cep::where('cep', $cep)
          ->get(['cep', 
          'logradouro', 
          'complemento', 
          'bairro', 
          'localidade',
          'uf','ibge']);
  
                  
          return response()->json($CEP, 200, ['Content-type'=> 'application/json; charset=utf-8'], JSON_PRETTY_PRINT | JSON_INVALID_UTF8_IGNORE);
      }else{
          return response()->json([
              "erro" => "endereço inválido"
          ], 404  );
      }
    }
    
  }

Feito nosso Controller, agora vamos apontar para a Rota que servirá de consumo para nossa API:

Agora tudo que temos que fazer é iniciar nossa aplicação:

php artisan serve

Façamos um teste no Isomnia:

Já está retornando conforme o esperado:

[
    {
        "cep": "01001000",
        "logradouro": "Praça da Sé - lado ímpar",
        "complemento": null,
        "bairro": "Sé",
        "localidade": "São Paulo",
        "uf": "SP",
        "ibge": 3550308
    }
]

Lembrando que nossa URL é a seguinte: localhost:8000/api/<número do cep>/JSON.

Vamos ver em uma aplicação de Cadastro de Clientes, no vídeo abaixo:

A aplicação acima, do excelente framework Adianti, do Pablo Dall´Oglio (Grande Referência de PHP no Brasil) está consumindo nossa API localmente, e retorna os valores de maneira automática, já falamos sobre este Padrão, o Observer (aqui).

Espero ter contribuído, por hoje me despeço!
Até breve! ; )

Código Fonte da API no Github

Base de CEP no Github

 

Alimente a força do Espírito que o protegerá no infortúnio inesperado, mas não se desespere com perigos imaginários, muitos temores nascem do cansaço e da solidão.

E a despeito de uma disciplina rigorosa, seja gentil para consigo mesmo. Portanto, esteja em paz com Deus, como quer que você O conceba, e quaisquer que sejam seus trabalhos e aspirações, na fatigante jornada da vida, mantenha-se em paz com sua própria alma.

Acima da falsidade, dos desencantos e agruras, o mundo ainda é bonito, seja prudente.
FAÇA TUDO PARA SER FELIZ

Trecho do Poema Desiderata