# Laravel 11: Construindo uma Aplicacao Completa do Zero > Guia completo para construir uma aplicacao com Laravel 11: autenticacao, API REST, Eloquent ORM e deploy em producao. Tutorial pratico para desenvolvedores iniciantes e intermediarios. - Published: 2026-01-14 - Updated: 2026-04-08 - Author: SharpSkill - Tags: laravel, php, rest api, eloquent, tutorial - Reading time: 15 min --- Laravel 11 redefine o desenvolvimento moderno em PHP com uma arquitetura simplificada e desempenho otimizado. Esta versao principal remove arquivos de configuracao desnecessarios, apresenta uma estrutura mais enxuta e melhora significativamente a experiencia do desenvolvedor. Este guia percorre a construcao de uma aplicacao completa de gerenciamento de tarefas, da instalacao ao deploy. > **Destaques do Laravel 11** > > Laravel 11 adota uma estrutura minimalista: sem arquivos Kernel, configuracao consolidada em bootstrap/app.php e um diretorio app/ mais limpo. O framework exige PHP 8.2 como minimo e integra SQLite nativamente para um inicio rapido. ## Instalacao e Configuracao do Projeto Laravel 11 pode ser instalado via Composer ou pelo instalador do Laravel. A nova estrutura do projeto e mais enxuta, com menos arquivos de configuracao para gerenciar desde o inicio. ```bash # terminal # Install the Laravel installer (recommended) composer global require laravel/installer # Create a new Laravel 11 project laravel new task-manager # Or directly with Composer composer create-project laravel/laravel task-manager # Navigate to the project cd task-manager ``` O instalador oferece diversas opcoes interativas: escolha de starter kit (Breeze, Jetstream), framework de testes (Pest, PHPUnit) e banco de dados. ```bash # terminal # Start the development server php artisan serve # Server starts at http://localhost:8000 ``` ### Configuracao do Banco de Dados Laravel 11 utiliza SQLite por padrao, ideal para desenvolvimento. Para aplicacoes em producao, a configuracao do MySQL ou PostgreSQL e feita no arquivo `.env`. ```env # .env # MySQL configuration DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=task_manager DB_USERNAME=root DB_PASSWORD=secret # PostgreSQL configuration (alternative) # DB_CONNECTION=pgsql # DB_HOST=127.0.0.1 # DB_PORT=5432 # DB_DATABASE=task_manager # DB_USERNAME=postgres # DB_PASSWORD=secret ``` A verificacao da conexao com o banco de dados e feita por meio de um comando Artisan. ```bash # terminal # Verify database connection php artisan db:show # Run default migrations php artisan migrate ``` ## Criacao de Models e Migrations O Eloquent ORM simplifica a manipulacao de dados com models expressivos. O comando `make:model` gera o model, a migration, o controller e o factory de uma so vez. ```bash # terminal # Generate Task model with migration, factory, seeder, and controller php artisan make:model Task -mfsc # -m : migration # -f : factory # -s : seeder # -c : controller ``` Esse comando cria quatro arquivos essenciais para o gerenciamento completo de tarefas. ```php id(); // Relationship with the owner user $table->foreignId('user_id')->constrained()->cascadeOnDelete(); // Task title (required) $table->string('title'); // Detailed description (optional) $table->text('description')->nullable(); // Status: pending, in_progress, completed $table->string('status')->default('pending'); // Priority: low, medium, high $table->string('priority')->default('medium'); // Due date (optional) $table->date('due_date')->nullable(); // Completion marker $table->timestamp('completed_at')->nullable(); // Automatic timestamps (created_at, updated_at) $table->timestamps(); // Soft deletes for trash functionality $table->softDeletes(); // Indexes to optimize frequent queries $table->index(['user_id', 'status']); $table->index('due_date'); }); } public function down(): void { Schema::dropIfExists('tasks'); } }; ``` A migration define a estrutura da tabela com relacionamentos, indices e soft delete para prevenir a perda acidental de dados. ```php 'date', 'completed_at' => 'datetime', ]; } // Constants for valid statuses public const STATUS_PENDING = 'pending'; public const STATUS_IN_PROGRESS = 'in_progress'; public const STATUS_COMPLETED = 'completed'; // Constants for priorities public const PRIORITY_LOW = 'low'; public const PRIORITY_MEDIUM = 'medium'; public const PRIORITY_HIGH = 'high'; // Relationship: a task belongs to a user public function user(): BelongsTo { return $this->belongsTo(User::class); } // Scope: pending tasks public function scopePending(Builder $query): Builder { return $query->where('status', self::STATUS_PENDING); } // Scope: in-progress tasks public function scopeInProgress(Builder $query): Builder { return $query->where('status', self::STATUS_IN_PROGRESS); } // Scope: completed tasks public function scopeCompleted(Builder $query): Builder { return $query->where('status', self::STATUS_COMPLETED); } // Scope: overdue tasks public function scopeOverdue(Builder $query): Builder { return $query->where('due_date', '<', now()) ->whereNull('completed_at'); } // Scope: tasks for a specific user public function scopeForUser(Builder $query, int $userId): Builder { return $query->where('user_id', $userId); } // Accessor: check if task is overdue public function getIsOverdueAttribute(): bool { return $this->due_date && $this->due_date->isPast() && !$this->completed_at; } // Method: mark as completed public function markAsCompleted(): void { $this->update([ 'status' => self::STATUS_COMPLETED, 'completed_at' => now(), ]); } } ``` O model Task utiliza Eloquent scopes para consultas legíveis e reutilizaveis. As constantes centralizam os valores validos para status e prioridades. > **Soft Deletes** > > O trait SoftDeletes adiciona uma coluna deleted_at. As tarefas excluidas nao desaparecem do banco de dados, apenas ficam marcadas como excluidas. Utilize withTrashed() para inclui-las nas consultas. ## Configuracao de Autenticacao com Breeze Laravel Breeze oferece autenticacao completa com views Blade ou uma API. A instalacao leva poucos minutos e gera tudo o necessario: rotas, controllers, views e testes. ```bash # terminal # Install Laravel Breeze composer require laravel/breeze --dev # Install the Blade stack (traditional) php artisan breeze:install blade # Or for API only (SPA/mobile) php artisan breeze:install api # Compile assets npm install && npm run build # Run migrations (users, sessions tables, etc.) php artisan migrate ``` O Breeze gera rotas de autenticacao, controllers e views para registro, login, redefinicao de senha e verificacao de e-mail. ```php 'datetime', 'password' => 'hashed', ]; } // Relationship: a user owns multiple tasks public function tasks(): HasMany { return $this->hasMany(Task::class); } // Shortcut: user's pending tasks public function pendingTasks(): HasMany { return $this->tasks()->pending(); } // Shortcut: user's overdue tasks public function overdueTasks(): HasMany { return $this->tasks()->overdue(); } } ``` ## Criacao de Controllers e Rotas O controller orquestra a logica de negocio entre as requisicoes HTTP e o model. Laravel 11 incentiva controllers de acao unica ou recursos RESTful. ```php user() ->tasks() ->when($request->status, fn($q, $status) => $q->where('status', $status)) ->when($request->priority, fn($q, $priority) => $q->where('priority', $priority)) ->orderBy('due_date') ->orderBy('priority', 'desc') ->paginate(15); return view('tasks.index', compact('tasks')); } // Creation form public function create(): View { return view('tasks.create'); } // Store a new task public function store(Request $request): RedirectResponse { // Validate incoming data $validated = $request->validate([ 'title' => 'required|string|max:255', 'description' => 'nullable|string|max:5000', 'priority' => 'required|in:low,medium,high', 'due_date' => 'nullable|date|after_or_equal:today', ]); // Create the task linked to the user $request->user()->tasks()->create($validated); return redirect() ->route('tasks.index') ->with('success', 'Task created successfully.'); } // Display a task public function show(Task $task): View { // Verify user ownership Gate::authorize('view', $task); return view('tasks.show', compact('task')); } // Edit form public function edit(Task $task): View { Gate::authorize('update', $task); return view('tasks.edit', compact('task')); } // Update a task public function update(Request $request, Task $task): RedirectResponse { Gate::authorize('update', $task); $validated = $request->validate([ 'title' => 'required|string|max:255', 'description' => 'nullable|string|max:5000', 'status' => 'required|in:pending,in_progress,completed', 'priority' => 'required|in:low,medium,high', 'due_date' => 'nullable|date', ]); // Update completed_at if status = completed if ($validated['status'] === Task::STATUS_COMPLETED && !$task->completed_at) { $validated['completed_at'] = now(); } $task->update($validated); return redirect() ->route('tasks.index') ->with('success', 'Task updated.'); } // Delete a task public function destroy(Task $task): RedirectResponse { Gate::authorize('delete', $task); $task->delete(); return redirect() ->route('tasks.index') ->with('success', 'Task deleted.'); } // Mark as completed (quick action) public function complete(Task $task): RedirectResponse { Gate::authorize('update', $task); $task->markAsCompleted(); return back()->with('success', 'Task completed!'); } } ``` O controller utiliza Gates para autorizacao, validacao integrada e route model binding para um codigo conciso e seguro. ### Definicao de Rotas As rotas definem URLs e as associam a acoes do controller. Laravel 11 centraliza as rotas em `routes/web.php`. ```php group(function () { // Dashboard with statistics Route::get('/dashboard', function () { $user = auth()->user(); return view('dashboard', [ 'totalTasks' => $user->tasks()->count(), 'pendingTasks' => $user->tasks()->pending()->count(), 'completedTasks' => $user->tasks()->completed()->count(), 'overdueTasks' => $user->tasks()->overdue()->count(), ]); })->name('dashboard'); // RESTful routes for tasks Route::resource('tasks', TaskController::class); // Quick action to complete a task Route::patch('/tasks/{task}/complete', [TaskController::class, 'complete']) ->name('tasks.complete'); // Profile routes (generated by Breeze) Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit'); Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update'); Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy'); }); // Authentication routes (generated by Breeze) require __DIR__.'/auth.php'; ``` O metodo `Route::resource()` gera automaticamente as sete rotas RESTful padrao: index, create, store, show, edit, update e destroy. ## Configuracao de Policies de Autorizacao As policies centralizam a logica de autorizacao para cada model. Elas determinam quem pode executar quais acoes sobre os recursos. ```bash # terminal # Generate the policy for Task php artisan make:policy TaskPolicy --model=Task ``` ```php is_admin) { return true; } return null; // Continue to specific methods } // Can view the list of tasks public function viewAny(User $user): bool { return true; // Any authenticated user } // Can view a specific task public function view(User $user, Task $task): bool { return $user->id === $task->user_id; } // Can create a task public function create(User $user): bool { return true; } // Can update a task public function update(User $user, Task $task): bool { return $user->id === $task->user_id; } // Can delete a task public function delete(User $user, Task $task): bool { return $user->id === $task->user_id; } // Can restore a soft-deleted task public function restore(User $user, Task $task): bool { return $user->id === $task->user_id; } // Can permanently delete public function forceDelete(User $user, Task $task): bool { return $user->id === $task->user_id; } } ``` O Laravel descobre automaticamente as policies por convencao de nomes. A `TaskPolicy` se aplica ao model `Task`. > **Seguranca das Policies** > > As policies sao essenciais para a seguranca. Sem elas, um usuario poderia manipular URLs para acessar tarefas de outros usuarios. A verificacao de propriedade dos recursos deve ser feita sempre. ## Construcao de uma API REST Laravel simplifica a criacao de APIs RESTful com rotas dedicadas, recursos JSON e Sanctum para autenticacao. ```bash # terminal # Install Sanctum (included by default since Laravel 11) php artisan install:api # This command: # - Publishes Sanctum migrations # - Adds the HasApiTokens trait to the User model # - Configures API routes ``` ```php user() ->tasks() ->when($request->status, fn($q, $s) => $q->where('status', $s)) ->when($request->priority, fn($q, $p) => $q->where('priority', $p)) ->when($request->boolean('overdue'), fn($q) => $q->overdue()) ->latest() ->paginate($request->input('per_page', 15)); return TaskResource::collection($tasks); } // Create a task public function store(Request $request): JsonResponse { $validated = $request->validate([ 'title' => 'required|string|max:255', 'description' => 'nullable|string|max:5000', 'priority' => 'required|in:low,medium,high', 'due_date' => 'nullable|date|after_or_equal:today', ]); $task = $request->user()->tasks()->create($validated); return response()->json([ 'message' => 'Task created successfully.', 'data' => new TaskResource($task), ], 201); } // Display a task public function show(Task $task): TaskResource { $this->authorize('view', $task); return new TaskResource($task); } // Update a task public function update(Request $request, Task $task): TaskResource { $this->authorize('update', $task); $validated = $request->validate([ 'title' => 'sometimes|required|string|max:255', 'description' => 'nullable|string|max:5000', 'status' => 'sometimes|required|in:pending,in_progress,completed', 'priority' => 'sometimes|required|in:low,medium,high', 'due_date' => 'nullable|date', ]); if (isset($validated['status']) && $validated['status'] === Task::STATUS_COMPLETED && !$task->completed_at) { $validated['completed_at'] = now(); } $task->update($validated); return new TaskResource($task->fresh()); } // Delete a task public function destroy(Task $task): JsonResponse { $this->authorize('delete', $task); $task->delete(); return response()->json([ 'message' => 'Task deleted successfully.', ]); } } ``` ### API Resources para Transformacao de Dados Os API Resources transformam models Eloquent em respostas JSON estruturadas, controlando com precisao os dados expostos. ```php $this->id, 'title' => $this->title, 'description' => $this->description, 'status' => $this->status, 'priority' => $this->priority, 'due_date' => $this->due_date?->format('Y-m-d'), 'is_overdue' => $this->is_overdue, 'completed_at' => $this->completed_at?->toISOString(), 'created_at' => $this->created_at->toISOString(), 'updated_at' => $this->updated_at->toISOString(), // Conditional inclusion of the user 'user' => $this->whenLoaded('user', fn() => [ 'id' => $this->user->id, 'name' => $this->user->name, ]), ]; } } ``` ### Rotas da API com Autenticacao Sanctum ```php user(); })->middleware('auth:sanctum'); // API routes protected by Sanctum Route::middleware('auth:sanctum')->group(function () { Route::apiResource('tasks', TaskController::class); // Dashboard statistics Route::get('/dashboard/stats', function (Request $request) { $user = $request->user(); return response()->json([ 'total' => $user->tasks()->count(), 'pending' => $user->tasks()->pending()->count(), 'in_progress' => $user->tasks()->inProgress()->count(), 'completed' => $user->tasks()->completed()->count(), 'overdue' => $user->tasks()->overdue()->count(), ]); }); }); ``` ## Testes Automatizados com Pest Laravel 11 integra o Pest PHP por padrao, um framework de testes elegante e expressivo. Os testes garantem que a aplicacao funcione corretamente apos cada modificacao. ```php create(); $tasks = Task::factory()->count(5)->for($user)->create(); $response = $this->actingAs($user)->get('/tasks'); $response->assertOk(); $response->assertViewHas('tasks'); }); // Test: a user can create a task test('user can create a task', function () { $user = User::factory()->create(); $response = $this->actingAs($user)->post('/tasks', [ 'title' => 'New task', 'description' => 'Task description', 'priority' => 'high', 'due_date' => now()->addDays(7)->format('Y-m-d'), ]); $response->assertRedirect('/tasks'); $this->assertDatabaseHas('tasks', [ 'user_id' => $user->id, 'title' => 'New task', 'priority' => 'high', ]); }); // Test: title validation required test('task title is required', function () { $user = User::factory()->create(); $response = $this->actingAs($user)->post('/tasks', [ 'title' => '', 'priority' => 'medium', ]); $response->assertSessionHasErrors('title'); }); // Test: a user cannot view another user's task test('user cannot view another users task', function () { $user = User::factory()->create(); $otherUser = User::factory()->create(); $task = Task::factory()->for($otherUser)->create(); $response = $this->actingAs($user)->get("/tasks/{$task->id}"); $response->assertForbidden(); }); // Test: mark a task as completed test('user can complete a task', function () { $user = User::factory()->create(); $task = Task::factory()->for($user)->create(['status' => 'pending']); $response = $this->actingAs($user)->patch("/tasks/{$task->id}/complete"); $response->assertRedirect(); $task->refresh(); expect($task->status)->toBe('completed'); expect($task->completed_at)->not->toBeNull(); }); // API test: retrieve tasks test('api returns paginated tasks', function () { $user = User::factory()->create(); Task::factory()->count(20)->for($user)->create(); $response = $this->actingAs($user, 'sanctum') ->getJson('/api/tasks?per_page=10'); $response->assertOk() ->assertJsonCount(10, 'data') ->assertJsonStructure([ 'data' => [ '*' => ['id', 'title', 'status', 'priority', 'due_date'], ], 'links', 'meta', ]); }); ``` Execucao dos testes com Pest. ```bash # terminal # Run all tests php artisan test # Tests with code coverage php artisan test --coverage # Tests for a specific file php artisan test tests/Feature/TaskTest.php # Parallel tests (faster) php artisan test --parallel ``` ## Otimizacoes para Producao Antes do deploy, diversas otimizacoes melhoram o desempenho da aplicacao Laravel. ```bash # terminal # Cache configuration php artisan config:cache # Cache routes php artisan route:cache # Cache views php artisan view:cache # Optimize Composer autoloader composer install --optimize-autoloader --no-dev # Generate asset manifest npm run build ``` ### Configuracao do Arquivo .env para Producao ```env # .env.production APP_NAME="Task Manager" APP_ENV=production APP_DEBUG=false APP_URL=https://taskmanager.example.com # Cache and session via Redis (recommended) CACHE_DRIVER=redis SESSION_DRIVER=redis QUEUE_CONNECTION=redis REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 # Database DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_DATABASE=task_manager_prod DB_USERNAME=app_user DB_PASSWORD=strong_password_here # Mail MAIL_MAILER=smtp MAIL_HOST=smtp.mailgun.org MAIL_PORT=587 MAIL_USERNAME=postmaster@taskmanager.example.com MAIL_PASSWORD=secret MAIL_ENCRYPTION=tls ``` > **Variaveis Sensíveis** > > O arquivo .env nunca deve ser commitado no repositorio Git. Recomenda-se usar o .env.example como template e configurar as variaveis sensiveis diretamente no servidor de producao ou por meio de gerenciadores de segredos. ## Conclusao Laravel 11 simplifica significativamente o desenvolvimento moderno em PHP com sua estrutura otimizada e convencoes inteligentes. Este guia cobriu os fundamentos para construir uma aplicacao completa: models Eloquent, autenticacao, controllers RESTful, policies de autorizacao, API com Sanctum e testes automatizados. ### Checklist para Aplicacoes Laravel de Qualidade - ✅ Usar migrations para todas as alteracoes de schema - ✅ Implementar policies para proteger o acesso aos recursos - ✅ Validar toda entrada do usuario nos controllers - ✅ Usar API Resources para controlar os dados expostos - ✅ Escrever testes para as funcionalidades criticas - ✅ Configurar cache e otimizacoes antes do deploy - ✅ Proteger as variaveis de ambiente sensiveis O ecossistema do Laravel continua evoluindo com pacotes como Livewire para interfaces reativas, Horizon para gerenciamento de filas e Octane para desempenho excepcional. Dominar esses fundamentos abre caminho para aplicacoes PHP robustas e manteniveís. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/pt/blog/laravel/laravel-11-building-complete-application