PHP Projetos
Nas aulas, você aprendeu uma peça de cada vez. Nos projetos, as peças se juntam: cada um é um pequeno sistema que funciona de verdade, construído em etapas, do arquivo vazio até o código completo. É aqui que "eu entendi a aula" vira "eu sei fazer".
- Os seis projetos, em que ordem fazer e quais aulas cada um usa.
- Como uma página de projeto é organizada.
- Como rodar os projetos no seu computador com o
php -Se testar com o navegador ou com ocurl. - O "esqueleto" que todos os projetos repetem, para você praticar antes de começar.
Os projetos
Faça na ordem: cada projeto reaproveita o que o anterior ensinou. Os quatro primeiros pedem só o Nível 1 e a parte de formulários do Nível 2; o login e os seguintes usam banco de dados e sessão.
| Projeto | O que você constrói | Aulas que ele usa |
|---|---|---|
| Calculadora Web | Dois números, quatro operações, resultado no formato 1.234,50; validação e divisão por zero | PHP Dentro do HTML, Formulários, $_GET e $_POST, match, Validar Dados, Escapar a Saída, Formatar Números |
| Formulário de Contato | Formulário com erros ao lado de cada campo, mensagens salvas em CSV ou JSON, sem envio duplicado | Validar Dados, mbstring, Arquivos, CSV, JSON, Redirecionamento, Datas |
| Login com Sessão | Cadastro, login, área restrita e logout, com senha em hash, sessão renovada e token CSRF | Sessões, Cookies, Senhas, CSRF, PDO, Prepared Statements, include e require |
| Tarefas com SQLite | Lista de tarefas com criar, listar, marcar, editar e excluir (CRUD); uma injeção de SQL demonstrada e evitada | Banco de Dados, PDO, CRUD com PDO, Prepared Statements |
| Mini Blog | Posts no SQLite, página de cada post, formulário de novo post, cabeçalho e rodapé incluídos, paginação | include e require, CRUD com PDO, Prepared Statements, $_GET e $_POST, Escapar a Saída, Datas |
| API REST | Uma API de tarefas em JSON, com GET, POST, PUT e DELETE e os códigos de status certos, testada com o curl | JSON, $_SERVER, Criar uma API JSON, PDO, Prepared Statements |
Se uma aula da lista ainda não foi feita, faça-a antes: o projeto explica cada linha nova, mas não repete a aula inteira.
Como uma página de projeto é organizada
- Antes de começar: o que o projeto usa e as aulas de cada coisa; os arquivos do projeto.
- As etapas: o projeto cresce uma novidade por vez. Cada etapa mostra só o código novo, explica cada parte (tabela ou "anatomia"), mostra a saída real (conferida com o PHP 8.5 rodando de verdade) e termina com uma caixa Experimente, que tem o arquivo completo daquela etapa e uma missão.
- Quando dá errado: as mensagens de erro que aparecem nesse tipo de projeto, com a mensagem completa, o que ela quer dizer e como consertar.
- O código completo: a versão final, para copiar e comparar com a sua.
- Desafios extras (sem resposta pronta), uma missão final, exercícios e resumo.
As caixas "Experimente" dos projetos
Nos projetos, as caixas funcionam no modo web: o código roda como uma página de site, servida pelo PHP de verdade dentro do seu navegador (veja O Editor do Guia).
- A aba Resultado mostra a página como o navegador mostraria. Formulários, links e redirecionamentos funcionam, e a sessão, os cookies e o banco SQLite continuam existindo entre um clique e outro, até você rodar de novo.
- A aba Código-fonte HTML mostra o HTML que o PHP gerou (é o que o
curlmostra no terminal). - Quando o projeto tem vários arquivos, cada um é uma aba do editor. O primeiro é a página que abre.
- Muitas caixas já começam com um envio de formulário pronto (por exemplo, "dividir 10 por 4"), para a missão poder ser conferida na hora. Depois disso, use o formulário na aba Resultado à vontade.
Rodando no seu computador
Você não precisa instalar um servidor como o Apache para estudar: o próprio PHP tem um servidor embutido (veja O Servidor Embutido). A rotina de todo projeto é esta:
- Crie uma pasta para o projeto e salve os arquivos nela.
- Num terminal, entre na pasta e suba o servidor. Deixe esse terminal aberto: ele é o servidor, e cada visita aparece nele.
- Abra
http://localhost:8000no navegador. - Para parar o servidor, volte ao terminal dele e aperte Ctrl+C.
Um exemplo pequeno, com o mesmo formato dos projetos (o index.php da caixa logo abaixo):
$ mkdir ola $ cd ola $ nano index.php « cole o código e salve $ php -S localhost:8000 [Fri Oct 16 21:09:29 2026] PHP 8.5.8 Development Server (http://localhost:8000) started [Fri Oct 16 21:09:30 2026] 127.0.0.1:49694 Accepted [Fri Oct 16 21:09:30 2026] 127.0.0.1:49694 [200]: GET / [Fri Oct 16 21:09:30 2026] 127.0.0.1:49694 Closing [Fri Oct 16 21:09:30 2026] 127.0.0.1:49700 Accepted [Fri Oct 16 21:09:30 2026] 127.0.0.1:49700 [200]: GET /?nome=Ana [Fri Oct 16 21:09:30 2026] 127.0.0.1:49700 Closing
Cada visita gera três linhas: a conexão aceita (Accepted), o pedido com o código da resposta ([200]: GET /?nome=Ana) e o fim da conexão (Closing). Quando o PHP der um erro fatal, ele também aparece aqui, no fim da linha do pedido.
Testando com o curl
Nas páginas dos projetos, as saídas foram conferidas com o curl, um programa de terminal que faz o papel do navegador e mostra o HTML que chegou. Ele é ótimo para ver exatamente o que o PHP respondeu. Use-o num segundo terminal, com o servidor rodando no primeiro:
$ curl -s localhost:8000/
<!DOCTYPE html>
<html lang="pt-BR">
<head><meta charset="utf-8"><title>Olá</title></head>
<body>
<form>
<input name="nome" placeholder="Seu nome">
<button>Enviar</button>
</form>
</body>
</html>
$ curl -s "localhost:8000/?nome=Ana" | grep Olá
<head><meta charset="utf-8"><title>Olá</title></head>
<p>Olá, Ana!</p>
$ curl -si "localhost:8000/?nome=Ana" | head -6
HTTP/1.1 200 OK
Host: localhost:8000
Date: Sat, 17 Oct 2026 00:09:30 GMT
Connection: close
X-Powered-By: PHP/8.5.8
Content-type: text/html; charset=UTF-8
| Como aparece nos projetos | O que faz |
|---|---|
curl -s URL | Busca a página (GET) e mostra o HTML. O -s (silent) esconde a barra de progresso. |
curl -s -d 'a=10&b=4' URL | Envia um formulário por POST com esses campos, como um clique no botão. |
curl -si URL | O -i mostra também os cabeçalhos da resposta (código, Location, Set-Cookie…). |
curl -sL URL | O -L segue redirecionamentos, como o navegador. |
curl -c jar.txt -b jar.txt URL | Guarda (-c) e devolve (-b) os cookies num arquivo: é assim que o curl "continua logado" entre um comando e outro. |
… | grep texto | Mostra só as linhas do HTML que contêm o texto, para não encher a tela. |
… | tail -5, … | head -8 | Só as últimas 5 / as primeiras 8 linhas. |
Use o navegador para usar o projeto, e o curl quando quiser ver por dentro: os cabeçalhos de um redirecionamento, o cookie da sessão, o HTML exato de um campo escapado. No navegador, o equivalente é a ferramenta do desenvolvedor (F12, aba Rede).
Caixa livre: este é o index.php do exemplo. A caixa já abre com ?nome=Ana; clique em voltar ou rode de novo e use o formulário com o seu nome. Veja também a aba Código-fonte HTML.
<?php
$nome = trim($_GET['nome'] ?? '');
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head><meta charset="utf-8"><title>Olá</title></head>
<body>
<?php if ($nome === ''): ?>
<form>
<input name="nome" placeholder="Seu nome">
<button>Enviar</button>
</form>
<?php else: ?>
<p>Olá, <?= htmlspecialchars($nome) ?>!</p>
<?php endif; ?>
</body>
</html>
O esqueleto de todo projeto
Repare na forma do arquivo, porque ela vai se repetir em todos os projetos:
- No topo, só PHP: ler o que chegou (
$_GET,$_POST), validar, gravar, redirecionar. Nada é impresso aqui. - Embaixo, o HTML: com pedacinhos de PHP só para mostrar (
<?= … ?>) e decidir o que aparece (<?php if (…): ?> … <?php endif; ?>). - Tudo que veio do usuário passa por
htmlspecialcharsantes de ir para a página.
Essa separação não é enfeite: funções como header() (redirecionar) e session_start() só funcionam antes de a página começar a sair. Com o PHP todo no topo, isso fica garantido.
Missão: mostre o nome em letras maiúsculas: Olá, ANA!. Use mb_strtoupper($nome) (a versão que entende acentos: experimente depois com "Zé") e não tire o htmlspecialchars.
<?php
$nome = trim($_GET['nome'] ?? '');
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head><meta charset="utf-8"><title>Olá</title></head>
<body>
<?php if ($nome === ''): ?>
<form>
<input name="nome" placeholder="Seu nome">
<button>Enviar</button>
</form>
<?php else: ?>
<p>Olá, <?= htmlspecialchars($nome) ?>!</p>
<?php endif; ?>
</body>
</html>
<?php
$nome = trim($_GET['nome'] ?? '');
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head><meta charset="utf-8"><title>Olá</title></head>
<body>
<?php if ($nome === ''): ?>
<form>
<input name="nome" placeholder="Seu nome">
<button>Enviar</button>
</form>
<?php else: ?>
<p>Olá, <?= htmlspecialchars(mb_strtoupper($nome)) ?>!</p>
<?php endif; ?>
</body>
</html>
Quando dá errado
$ php -S localhost:8000 [Fri Oct 16 21:09:30 2026] Failed to listen on localhost:8000 (reason: Address in use)
O que significa: "endereço em uso": outro programa já está usando a porta 8000, quase sempre um php -S de outro projeto, esquecido noutro terminal. Como consertar: pare o outro (Ctrl+C no terminal dele) ou use outra porta: php -S localhost:8001 e http://localhost:8001.
Você abriu o arquivo direto (endereço começando com file://). Só o servidor executa o PHP: abra http://localhost:8000.
index.php
$ curl -s localhost:8000/nada.php
<!DOCTYPE html>
<html lang="pt-BR">
<head><meta charset="utf-8"><title>Olá</title></head>
<body>
<form>
<input name="nome" placeholder="Seu nome">
<button>Enviar</button>
</form>
</body>
</html>
Não existe nada.php, mas o servidor embutido, quando não acha o arquivo pedido, responde com o index.php da pasta. Se um link "não funciona" e você sempre volta à página inicial, confira o nome do arquivo no link.
Confira se você salvou o arquivo, se o servidor está rodando na pasta certa (a pasta onde você deu o php -S) e recarregue a página. Num formulário, recarregar com F5 depois de um envio pode reenviar os dados: abra o endereço de novo em vez disso.
Exercícios
Complete o comando que sobe o servidor embutido na porta 8000:
Qual opção do curl envia um formulário por POST?
Por que os projetos põem todo o PHP de "processar" no topo do arquivo, antes do HTML?
Resumo
- Seis projetos, na ordem: calculadora, contato, login, tarefas, blog e API.
- Cada um cresce em etapas: código novo explicado, saída real e uma caixa Experimente com missão.
- No seu computador:
php -S localhost:8000na pasta do projeto,http://localhost:8000no navegador, Ctrl+C para parar. - O
curlmostra a resposta por dentro:-denvia POST,-imostra cabeçalhos,-Lsegue redirecionamentos,-c/-bguardam cookies.
Comece pela Calculadora Web.