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
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
Passo 3 — Criando a migration
As migrations permitem versionar e criar tabelas no banco.
Execute:
php artisan make:migration create_tasks_table --create=tasks
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();
});
Crie a tabela:
php artisan migrate
Passo 4 — Criando Model e Controller
Laravel segue o padrão MVC.
php artisan make:model Task
php artisan make:controller TaskController --api
No modelo app/Models/Task.php:
class Task extends Model
{
    use HasFactory;
    protected $fillable = ['title', 'description', 'completed'];
}
Passo 5 — Definindo rotas
No routes/api.php:
Route::apiResource('tasks', TaskController::class);
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);
    }
}
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
Passo 8 — Automatizando testes com PHPUnit
Crie uma factory:
php artisan make:factory TaskFactory
database/factories/TaskFactory.php:
public function definition(): array
{
    return [
        'title' => fake()->sentence(),
        'description' => fake()->paragraph(),
        'completed' => false,
    ];
}
Crie o teste:
php artisan make:test TaskApiTest
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);
    }
}
Execute:
php artisan test
 

 
    
Top comments (0)