DEV Community

Carlos Viana
Carlos Viana

Posted on • Edited on

Criando uma API REST com Laravel

Criando uma API RESTful Completa com Laravel

Neste tutorial, vamos construir uma API RESTful completa em Laravel para gerenciar tarefas, aproveitando todo o poder do framework — que é voltado para produtividade, clareza e robustez.

O Laravel foi criado e é mantido por Taylor Otwell, sendo um framework opiniativo que prioriza convenções sobre configurações. Isso significa menos tempo gasto com ajustes manuais e mais foco na lógica de negócio.


O que é uma API RESTful?

Antes de codificar, é importante entender o conceito.

REST (Representational State Transfer) é um estilo arquitetural para comunicação entre sistemas, normalmente usando o protocolo HTTP.
Nas APIs RESTful:

  • Os endpoints representam recursos.
  • Os verbos HTTP indicam ações:

    • GET → Recuperar recursos
    • POST → Criar recursos
    • PUT → Atualizar recursos
    • DELETE → Excluir recursos

Cada requisição é sem estado (stateless), ou seja, o servidor não guarda contexto entre chamadas.


Passo 1 — Criando o projeto Laravel

Com PHP e Composer instalados, crie o projeto:

composer create-project laravel/laravel task-api
Enter fullscreen mode Exit fullscreen mode

Abra o projeto no VS Code ou no editor de sua preferência.


Passo 2 — Configurando o banco de dados

No arquivo .env, ajuste para o seu ambiente:

DB_DATABASE=task_api
DB_USERNAME=seu_usuario
DB_PASSWORD=sua_senha
Enter fullscreen mode Exit fullscreen mode

Passo 3 — Criando a migration

As migrations permitem versionar e criar tabelas no banco.
Execute:

php artisan make:migration create_tasks_table --create=tasks
Enter fullscreen mode Exit fullscreen mode

Defina a estrutura em database/migrations/xxxx_xx_xx_create_tasks_table.php:

Schema::create('tasks', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('description')->nullable();
    $table->boolean('completed')->default(false);
    $table->timestamps();
});
Enter fullscreen mode Exit fullscreen mode

Crie a tabela:

php artisan migrate
Enter fullscreen mode Exit fullscreen mode

Passo 4 — Criando Model e Controller

Laravel segue o padrão MVC.

php artisan make:model Task
php artisan make:controller TaskController --api
Enter fullscreen mode Exit fullscreen mode

No modelo app/Models/Task.php:

class Task extends Model
{
    use HasFactory;

    protected $fillable = ['title', 'description', 'completed'];
}
Enter fullscreen mode Exit fullscreen mode

Passo 5 — Definindo rotas

No routes/api.php:

Route::apiResource('tasks', TaskController::class);
Enter fullscreen mode Exit fullscreen mode

Isso já cria automaticamente todas as rotas CRUD.


Passo 6 — Implementando o Controller

Em app/Http/Controllers/TaskController.php:

<?php 

namespace App\Http\Controllers; 
use App\Models\Task; 
use Illuminate\Http\Request; 

class TaskController extends Controller { 
    public function index()
    {
        return response()->json(Task::all(), 200);
    }

    public function store(Request $request)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'description' => 'nullable|string'
        ]);

        $task = Task::create($request->all());
        return response()->json($task, 201);
    }

    public function show(Task $task)
    {
        return response()->json($task, 200);
    }

    public function update(Request $request, Task $task)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'description' => 'nullable|string',
            'completed' => 'boolean'
        ]);

        $task->update($request->all());
        return response()->json($task, 200);
    }

    public function destroy(Task $task)
    {
        $task->delete();
        return response()->json(null, 204);
    }
}
Enter fullscreen mode Exit fullscreen mode

Passo 7 — Testando a API

Você pode testar com Postman, Insomnia ou com a extensão REST Client no VS Code.

Exemplo de requisição .http:

### Criar nova tarefa
POST http://127.0.0.1:8000/api/tasks
Content-Type: application/json

{
    "title": "Estudar Laravel"
}

### Listar tarefas
GET http://127.0.0.1:8000/api/tasks
Enter fullscreen mode Exit fullscreen mode

Passo 8 — Automatizando testes com PHPUnit

Crie uma factory:

php artisan make:factory TaskFactory
Enter fullscreen mode Exit fullscreen mode

database/factories/TaskFactory.php:

public function definition(): array
{
    return [
        'title' => fake()->sentence(),
        'description' => fake()->paragraph(),
        'completed' => false,
    ];
}
Enter fullscreen mode Exit fullscreen mode

Crie o teste:

php artisan make:test TaskApiTest
Enter fullscreen mode Exit fullscreen mode

tests/Feature/TaskApiTest.php (exemplo de teste de criação):

<?php

namespace Tests\Feature;

use App\Models\Task;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class TaskApiTest extends TestCase
{
    use RefreshDatabase;

    public function test_can_create_task(): void
    {
        $response = $this->postJson('/api/tasks', [
            'title' => 'Nova Tarefa',
            'description' => 'Descrição da tarefa',
            'completed' => false,
        ]);

        $response->assertStatus(201);
        $response->assertJson([
            'title' => 'Nova Tarefa',
            'description' => 'Descrição da tarefa',
            'completed' => false,
        ]);
    }

    public function test_can_list_tasks(): void
    {
        Task::factory()->count(3)->create();

        $response = $this->getJson('/api/tasks');

        $response->assertStatus(200);
        $response->assertJsonCount(3);
    }

    public function test_can_show_task(): void
    {
        $task = Task::factory()->create();

        $response = $this->getJson("/api/tasks/{$task->id}");

        $response->assertStatus(200);
        $response->assertJson([
            'title' => $task->title,
        ]);
    }

    public function test_can_update_task(): void
    {
        $task = Task::factory()->create();

        $response = $this->putJson("/api/tasks/{$task->id}", [
            'title' => 'Tarefa Atualizada',
            'description' => 'Nova descrição',
            'completed' => true,
        ]);

        // Mantendo 201 para compatibilidade com o seu controller atual
        $response->assertStatus(201);
        $response->assertJson([
            'title' => 'Tarefa Atualizada',
            'description' => 'Nova descrição',
            'completed' => true,
        ]);
    }

    public function test_can_delete_task(): void
    {
        $task = Task::factory()->create();

        $response = $this->deleteJson("/api/tasks/{$task->id}");

        $response->assertStatus(204);
    }
}
Enter fullscreen mode Exit fullscreen mode

Execute:

php artisan test
Enter fullscreen mode Exit fullscreen mode

Top comments (0)