Artigo 41 — Introdução ao Laravel
Módulo 7 · Semana 41 · Nível: Intermediário
Introdução
Laravel é o framework PHP mais popular do mundo, e por boas razões. Ele não apenas resolve problemas técnicos — ele define uma forma de pensar sobre o desenvolvimento web. Com Laravel, você tem um roteador expressivo, ORM elegante, sistema de templates, autenticação, filas, eventos, testes e dezenas de outros recursos integrados e funcionando em harmonia desde o primeiro composer create-project.
Mas Laravel não é magia. Cada recurso que ele oferece é construído sobre os fundamentos que você já aprendeu: namespaces, PSR-4, injeção de dependência, interfaces, padrões de projeto. Entender isso transforma você de um usuário do framework em alguém que realmente domina o que está usando.
Instalação e estrutura
# Criando um novo projeto Laravel
composer create-project laravel/laravel minha-loja
cd minha-loja
# Iniciando o servidor de desenvolvimento
php artisan serve
# http://localhost:8000
# Ou com o Laravel Herd (recomendado para desenvolvimento local)
# https://herd.laravel.com/
Estrutura de diretórios:
minha-loja/
├── app/
│ ├── Http/
│ │ ├── Controllers/ ← Controladores
│ │ └── Middleware/ ← Middlewares HTTP
│ ├── Models/ ← Models Eloquent
│ ├── Providers/ ← Service Providers
│ └── Services/ ← Lógica de negócio (você cria)
├── bootstrap/ ← Bootstrap da aplicação
├── config/ ← Configurações (database, mail, etc.)
├── database/
│ ├── factories/ ← Factories para testes
│ ├── migrations/ ← Migrations de banco de dados
│ └── seeders/ ← Seeds de dados iniciais
├── public/ ← Document root (index.php)
├── resources/
│ └── views/ ← Templates Blade
├── routes/
│ ├── web.php ← Rotas web (com sessão, CSRF)
│ └── api.php ← Rotas API (stateless)
├── storage/ ← Logs, cache, uploads
├── tests/ ← Testes automatizados
├── .env ← Variáveis de ambiente
└── artisan ← CLI do Laravel
Configuração — o arquivo .env
# .env
APP_NAME="Minha Loja"
APP_ENV=local
APP_KEY=base64:... # Gerado automaticamente — nunca commite
APP_DEBUG=true
APP_URL=http://localhost:8000
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=minha_loja
DB_USERNAME=root
DB_PASSWORD=
MAIL_MAILER=smtp
MAIL_HOST=mailpit
MAIL_PORT=1025
O arquivo .env nunca vai para o git (está no .gitignore). Em vez disso, commite o .env.example com as chaves mas sem os valores sensíveis. Para gerar a APP_KEY:
php artisan key:generate
Roteamento
<?php
// routes/web.php
use App\Http\Controllers\ProdutoController;
use App\Http\Controllers\CarrinhoController;
use Illuminate\Support\Facades\Route;
// Rota simples com closure
Route::get('/', function () {
return view('home');
});
// Rota com parâmetro
Route::get('/produtos/{id}', function (int $id) {
return "Produto: {$id}";
});
// Rota com parâmetro opcional
Route::get('/blog/{slug?}', function (?string $slug = null) {
return $slug ? "Post: {$slug}" : "Lista do blog";
});
// Rota apontando para controller
Route::get('/produtos', [ProdutoController::class, 'index']);
Route::get('/produtos/{produto}', [ProdutoController::class, 'show']);
Route::post('/produtos', [ProdutoController::class, 'store']);
Route::put('/produtos/{produto}', [ProdutoController::class, 'update']);
Route::delete('/produtos/{produto}', [ProdutoController::class, 'destroy']);
// Resource route — cria as 7 rotas CRUD de uma vez
Route::resource('produtos', ProdutoController::class);
// Rotas agrupadas com prefixo e middleware
Route::middleware('auth')->prefix('admin')->group(function () {
Route::resource('produtos', ProdutoController::class);
Route::resource('pedidos', PedidoController::class);
});
// Rotas nomeadas — facilita geração de URLs
Route::get('/contato', [ContatoController::class, 'index'])->name('contato');
// Uso: route('contato') → /contato
Controllers
# Criar um controller com os métodos CRUD já estruturados
php artisan make:controller ProdutoController --resource
<?php
declare(strict_types=1);
namespace App\Http\Controllers;
use App\Models\Produto;
use App\Http\Requests\ProdutoRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;
class ProdutoController extends Controller
{
// GET /produtos
public function index(): View
{
$produtos = Produto::where('ativo', true)
->orderBy('nome')
->paginate(15);
return view('produtos.index', compact('produtos'));
}
// GET /produtos/{produto}
// O Laravel resolve automaticamente o Model pelo ID (Route Model Binding)
public function show(Produto $produto): View
{
return view('produtos.show', compact('produto'));
}
// GET /produtos/create
public function create(): View
{
return view('produtos.create');
}
// POST /produtos
public function store(ProdutoRequest $request): RedirectResponse
{
// $request->validated() retorna apenas os campos que passaram na validação
$produto = Produto::create($request->validated());
return redirect()
->route('produtos.show', $produto)
->with('sucesso', 'Produto criado com sucesso!');
}
// PUT /produtos/{produto}
public function update(ProdutoRequest $request, Produto $produto): RedirectResponse
{
$produto->update($request->validated());
return redirect()
->route('produtos.show', $produto)
->with('sucesso', 'Produto atualizado.');
}
// DELETE /produtos/{produto}
public function destroy(Produto $produto): RedirectResponse
{
$produto->delete();
return redirect()
->route('produtos.index')
->with('sucesso', 'Produto removido.');
}
}
Form Requests — validação encapsulada
php artisan make:request ProdutoRequest
<?php
declare(strict_types=1);
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ProdutoRequest extends FormRequest
{
// Autorização — quem pode fazer esta requisição?
public function authorize(): bool
{
return $this->user()?->isAdmin() ?? false;
}
// Regras de validação
public function rules(): array
{
return [
'nome' => ['required', 'string', 'min:3', 'max:200'],
'preco' => ['required', 'numeric', 'min:0'],
'estoque' => ['required', 'integer', 'min:0'],
'ativo' => ['boolean'],
'descricao'=> ['nullable', 'string', 'max:2000'],
'imagem' => ['nullable', 'image', 'max:2048'], // máx 2MB
];
}
// Mensagens customizadas
public function messages(): array
{
return [
'nome.required' => 'O nome do produto é obrigatório.',
'preco.min' => 'O preço não pode ser negativo.',
'imagem.image' => 'O arquivo deve ser uma imagem.',
'imagem.max' => 'A imagem deve ter no máximo 2MB.',
];
}
}
Service Container e Service Providers
O Service Container do Laravel é um container de DI poderoso. Você registra como criar objetos, e o Laravel injeta automaticamente onde forem necessários:
<?php
// app/Providers/AppServiceProvider.php
namespace App\Providers;
use App\Repositories\ProdutoRepositorioInterface;
use App\Repositories\EloquentProdutoRepositorio;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
// Bind interface → implementação concreta
$this->app->bind(
ProdutoRepositorioInterface::class,
EloquentProdutoRepositorio::class,
);
}
public function boot(): void
{
// Executado após todos os providers registrarem seus serviços
}
}
// Agora o controller pode declarar a interface no construtor:
class ProdutoController extends Controller
{
public function __construct(
private readonly ProdutoRepositorioInterface $repositorio,
) {}
}
// O Laravel injeta automaticamente a implementação concreta
Artisan — a CLI do Laravel
# Listar todos os comandos disponíveis
php artisan list
# Criar arquivos
php artisan make:model Produto -mfc # Model + migration + factory + controller
php artisan make:migration criar_tabela_pedidos
php artisan make:seeder ProdutoSeeder
php artisan make:job ProcessarPagamento
php artisan make:event PedidoCriado
php artisan make:listener EnviarEmailDePedido
php artisan make:command ImportarProdutos
# Executar
php artisan migrate # Roda as migrations pendentes
php artisan migrate:fresh --seed # Recria o banco e roda seeds
php artisan db:seed # Apenas seeds
php artisan queue:work # Processa filas
php artisan schedule:run # Executa tarefas agendadas
# Informações
php artisan route:list # Lista todas as rotas
php artisan config:show database # Exibe config do banco
php artisan tinker # REPL interativo — testado no console
Resumo
| Conceito | Laravel |
|---|---|
| Roteamento | routes/web.php — fluente, com grupos e middleware |
| Controllers | Classes em app/Http/Controllers/ — um método por ação |
| Validação | FormRequest encapsula regras e autorização |
| DI Container | ServiceProvider registra bindings — injeção automática |
| CLI | php artisan — gera código, migra banco, processa filas |
| Configuração | .env + config/ — nunca hardcode de credenciais |
Exercício da semana
-
Crie um projeto Laravel do zero. Configure o banco de dados. Crie um CRUD completo de
Categoriacom: migration, model, controller resource, form request com validação, e views Blade básicas. -
Adicione Route Model Binding ao CRUD: ao acessar
/categorias/{categoria}, o Laravel deve resolver automaticamente o model pelo ID e retornar 404 se não encontrar. -
Implemente uma interface
CategoriaRepositorioInterfacecom métodolistarAtivas(): Collection. Crie a implementação com Eloquent. Registre o binding noAppServiceProvider. Injete no controller. -
Desafio: crie um comando Artisan customizado
php artisan categorias:importar {arquivo}que leia um CSV e importe categorias no banco, exibindo progresso com$this->progressBar().
Referências
- Documentação oficial do Laravel: https://laravel.com/docs
- Laracasts (vídeos): https://laracasts.com/
- Laravel News: https://laravel-news.com/
- Awesome Laravel: https://github.com/chiraggude/awesome-laravel