thumbnail

Como consumir uma API com Laravel

Yuri do Monte Yuri do Monte | 10 min de leitura
há 1 semana

Como consumir uma API com Laravel e Livewire 

E aí, dev! Beleza? Sei que no início da jornada, integrar uma API externa pode parecer um monstro de sete cabeças. Mas relaxa, estou aqui para te mostrar um caminho mais tranquilo e produtivo. Neste guia, vamos juntos desmistificar esse processo usando o poder do Laravel e a mágica do Livewire.


Vamos construir uma aplicação simples, mas muito funcional: um buscador de previsão do tempo que consome a API da OpenWeatherMap. O objetivo é que, no final, você não só tenha um código legal para colocar no seu portfólio, mas que principalmente entenda os princípios por trás de uma boa integração. Vamos focar em criar um código limpo, organizado e fácil de dar manutenção. Afinal, código bom é aquele que o seu "eu do futuro" (ou outro dev) vai agradecer.

Bora lá? Pega seu café e vamos estruturar esse projeto.

Antes de sair escrevendo código, um bom dev prepara o terreno. Isso economiza uma dor de cabeça gigante no futuro. Vamos começar com o básico: a configuração.

Por que um arquivo de configuração? (config/openweather.php)

Poderíamos simplesmente colocar nossa chave de API direto no código, certo? Errado. Nunca, jamais, em hipótese alguma, comite chaves, senhas ou qualquer outra credencial direto no seu repositório. É uma falha de segurança grave.

Por isso, a primeira coisa que fazemos é criar um arquivo de configuração dedicado. Isso centraliza as informações e nos permite usar as variáveis de ambiente do Laravel, que é o lugar certo para guardar segredos.


<?php

// config/openweather.php
return [
    'api_key' => env('API_OPENWEATHER'),
    'url' => env('OPENWEATHER_BASE_API', 'https://api.openweathermap.org/' )
];


No seu arquivo .env, você adiciona as chaves:


API_OPENWEATHER=SUA_CHAVE_SECRETA_AQUI
OPENWEATHER_BASE_API=https://api.openweathermap.org/


Assim, seu código fica limpo e seguro. Se a chave mudar, você só altera o .env, sem tocar no código que já está em produção.

Rotas: O Porteiro da sua Aplicação (routes/web.php )

A rota é a porta de entrada. Manter as rotas limpas e legíveis é fundamental. Para o nosso caso, é bem simples:


<?php

// routes/web.php
use Illuminate\Support\Facades\Route;
use App\Livewire\Openweather;

// ... outras rotas

Route::get('/', Openweather::class);

Estamos dizendo ao Laravel: "Quando alguém chegar na página inicial (/), pode chamar a classe Openweather do Livewire para cuidar do resto". Simples, declarativo e direto ao ponto.


Isolando a Lógica: A Camada de Serviço (app/Services/OpenWeatherService.php)


Beleza, agora que a casa está em ordem, vamos falar de um conceito que vai elevar o nível do seu código: a cam

ada de serviço (Service Layer).

Em vez de fazer a chamada da API direto no nosso Controller (ou, no nosso caso, no componente Livewire), vamos delegar essa responsabilidade para uma classe específica. Por quê?


  1. Separação de Responsabilidades (SoC): Nosso componente Livewire não precisa saber como os dados do tempo são buscados. Ele só precisa pedir por eles. O Service é o especialista que sabe como conversar com a API da OpenWeather.
  2. Reutilização: Se amanhã você precisar desses mesmos dados em um comando Artisan ou em outra parte do sistema, é só chamar o mesmo Service. Nada de código duplicado.
  3. Testabilidade: Testar a lógica de chamada da API fica muito mais fácil quando ela está isolada em uma classe. Você pode criar um teste unitário só para o OpenWeatherService.

Vamos ver como fica o nosso:


<?php
// app/Services/OpenWeatherService.php
namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\RequestException;

class OpenWeatherService {

    private $api_key;
    
    public function __construct()
    {
        // Pegamos a chave do arquivo de config, não do env() diretamente!
        $this->api_key = config(\'services.openweather.api_key\');
    }
        
    // ... (métodos currentWeather e weatherForecast)

    private function getAPI($resource, $params = [])
    {
        $params[\'units\'] = \'metric\';
        $params[\'lang\']  = \'pt_br\';
        $params[\'appid\'] = $this->api_key;

        // Usamos o cliente HTTP do Laravel. O método throw() já cuida de erros HTTP para nós!
         return Http::baseUrl(config(\'services.openweather.url\'))
            ->get($resource, $params)
            ->throw() // Lança exceção para erros 4xx e 5xx
            ->json();
    }
}


Dica de Sênior: Note que no método getAPI, estamos usando Http::baseUrl(). Isso é um pouco mais limpo do que concatenar strings de URL. Além disso, o uso do ->throw() é crucial. Ele para a execução e lança uma RequestException se a API retornar um erro (como 401 - Não Autorizado ou 404 - Não Encontrado). Isso nos permite usar um bloco try-catch limpo nos métodos que o chamam, como o currentWeather, para tratar essas falhas de forma elegante.

Com nosso Service bem estruturado, a parte de consumir a API está resolvida de forma profissional. Agora vamos plugar isso no nosso front-end com o Livewire.


O Maestro da Interatividade: Componentes Livewire


Livewire é fantástico porque nos permite construir interfaces dinâmicas sem escrever rios de JavaScript. Ele cria uma ponte inteligente entre o front e o back-end. Pense no seu componente Livewire como um "Controller para o front-end".


O Componente Pai (app/Livewire/Openweather.php)

Este é o nosso componente principal. A responsabilidade dele é gerenciar o estado da busca (a cidade digitada) e orquestrar a chamada ao nosso Service.


<?php
// app/Livewire/Openweather.php
namespace App\Livewire;

use Livewire\Component;
use App\Services\OpenWeatherService;

class Openweather extends Component
{
    public $result;
    public $city = ";

    public function render()
    {
        return view(\'livewire.openweather\');
    }

    public function getCurrentWeather(OpenWeatherService $weatherService)
    {
        if ($this->city) {
            // Injetamos o Service em vez de instanciar. Mais limpo e melhor para testes!
            $this->result = $weatherService->currentWeather($this->city);
            
            // Disparamos um evento para quem quiser ouvir (nosso modal, por exemplo)
            $this->dispatch(\'cidadeAtualizada\', $this->city);
        }
    }
}


Dica de Sênior: Veja que no método getCurrentWeather, eu mudei a forma como obtemos o Service. Em vez de new OpenWeatherService(), estamos usando a injeção de dependência do Laravel (OpenWeatherService $weatherService). Por que isso é melhor? O Laravel se encarrega de criar a instância para nós. Isso facilita muito na hora de escrever testes, pois podemos facilmente "mockar" (simular) o OpenWeatherService para que ele retorne dados falsos, sem precisar fazer uma chamada real à API durante os testes.

Outro ponto chave é o $this->dispatch(). Estamos emitindo um evento. Isso desacopla nossos componentes. O Openweather não precisa saber que existe um modal. Ele só avisa: "A cidade mudou!". Quem tiver interesse, que ouça.

O Componente Filho: O Modal (app/Livewire/WeatherForecastModel.php)

Este componente é um bom exemplo de como criar partes reutilizáveis e reativas na sua UI. Ele só se preocupa em mostrar a previsão futura e só aparece quando é chamado.


<?php
// app/Livewire/WeatherForecastModel.php
namespace App\Livewire;

use Livewire\Component;
use App\Services\OpenWeatherService;

class WeatherForecastModel extends Component
{
    public $result;
    public $city;
    
    // Nosso "rádio" para ouvir o evento do componente pai
    protected $listeners = [\'cidadeAtualizada\' => \'getCity\'];
    
    public function getCity(OpenWeatherService $weatherService, $city)
    {
        $this->city = $city;
        $this->result = $weatherService->weatherForecast($this->city);
        
        // Dispara eventos JS para controlar o modal no front-end
        $this->dispatch(\'toggleForecastModal\');
    }
    
    public function render()
    {
        return view(\'livewire.weather-forecast-model\');
    }
}


O protected $listeners é a chave aqui. Ele cria o vínculo entre os componentes. Ao ouvir cidadeAtualizada, ele aciona o método getCity, que por sua vez busca os dados e dispara um evento para o JavaScript manipular o modal. Essa comunicação via eventos é um padrão poderoso para criar UIs complexas e organizadas.


A Mágica Visível: Views e um Pouco de JavaScript


O código Blade do Livewire é bem intuitivo. Ele se parece muito com o Blade que você já conhece, mas com superpoderes.


A View Principal (resources/views/livewire/openweather.blade.php)


<div id="container">
    <!-- Botão para o modal -->
    <button type="button" class="btn btn-primary" wire:click="$dispatch("toggleForecastModal")">
        Previsão Detalhada
    </button>

    <!-- Formulário de busca -->
    <form wire:submit.prevent="getCurrentWeather">
        <input type="search" placeholder="Buscar cidade" wire:model="city">
        <button type="submit">Buscar</button>
    </form>

    <!-- Exibição do resultado -->
    <div id="weather">
        @if ($result)
            @if (isset($result["error"]))
                <h1>{{ strtoupper($result["error"]) }}</h1>
            @else
                <h1>{{ strtoupper($city) }}</h1>
                <!-- Restante do HTML para exibir os dados -->
            @endif
        @endif
    </div>
</div>

Dica de Junior: Em vez de ter um botão separado com wire:click e um formulário com wire:submit, podemos simplificar. O wire:model já atualiza a propriedade $city em tempo real (com um pequeno debounce). Podemos usar wire:model.live para uma atualização instantânea ou wire:model.blur para atualizar só quando o usuário sai do campo. O wire:submit no formulário já é suficiente para acionar a busca.


O JavaScript (resources/js/weather.js)

Embora o Livewire reduza a necessidade de JS, às vezes ele é a melhor ferramenta para o trabalho, especialmente para interagir com bibliotecas de terceiros, como o Bootstrap.


// resources/js/weather.js
document.addEventListener("livewire:load", function () {
    const forecastModal = new bootstrap.Modal(document.getElementById("forecastModal"));

    Livewire.on("toggleForecastModal", () => {
        forecastModal.toggle();
    });
});


Aqui, inicializamos o modal do Bootstrap uma vez e depois apenas ouvimos o evento toggleForecastModal que nosso componente Livewire dispara. Quando o evento chega, simplesmente chamamos o método .toggle() do modal. É mais limpo e eficiente do que criar e destruir a instância do modal a cada evento.


Conclusão: Você no Controle


Pronto! Passamos por todas as etapas para construir uma integração com API de forma robusta e profissional. Mais importante do que o código em si, são os princípios que aplicamos:


  • Configuração Segura: Segredos ficam no .env, configurações em config/.
  • Separação de Responsabilidades: Usamos uma camada de Serviço para isolar a lógica da API.
  • Injeção de Dependência: Deixamos o Laravel gerenciar nossas classes, o que torna o código mais flexível e testável.
  • Comunicação via Eventos: Desacoplamos nossos componentes, permitindo que evoluam de forma independente.

Dominar esses conceitos vai te diferenciar como desenvolvedor. Eles são a base para construir aplicações maiores, mais complexas e, principalmente, mais fáceis de manter.

Espero que este guia tenha clareado as coisas para você. Continue estudando, aplicando esses padrões em seus projetos e não tenha medo de refatorar seu código para torná-lo melhor. Esse é o caminho para se tornar um dev cada vez mais completo.

Qualquer dúvida, manda aí! Tamo junto!

Comentários

Realize login para comentar neste post
Este post não possui comentários