Capítulo 13
Um formulário que chega por POST
6 min de leitura 999 palavras 1 gravura
Neste capítulo você vai enviar campos ao PHP local e reconhecer a resposta sem gravar ainda.
Seu ponto de partida
Estude depois do capítulo 12. O exemplo deste capítulo é 13-formulario-post, no pacote que acompanha o volume. Copie a pasta inicio para um diretório de prática e preserve o original. A raiz do exemplo é a referência concluída desta etapa. Sua cópia permite experimentar sem perder a referência.
Execute o PHP na raiz da sua cópia com php -S 127.0.0.1:8000 -t public. Abra http://127.0.0.1:8000/. Não abra PHP por duplo clique nem use o servidor de Python. Encerre com Ctrl+C antes de trocar de etapa.
Como praticar
Leia a explicação e digite ou confira o código indicado. Mude uma coisa. Antes de conferir, anote sua previsão. Salve, recarregue e compare. Se não acontecer o esperado, investigue o erro antes de avançar. Cada experiência parte dos valores da referência. Depois de conferir, desfaça somente a mudança desse experimento antes de começar a próxima lição. Você pode parar depois de uma lição e retomar mais tarde.
Ligue rótulo e campo
O formulário já está completo em public/index.php. Cada campo tem um rótulo visível. For no label combina com id no campo e permite focá-lo ao clicar no texto.
Name tem outra tarefa: identifica a chave que o PHP recebe em $_POST. Um id sozinho não cria essa chave. Method=post escolhe o tipo de envio; action=index.php aponta para este arquivo no servidor local.
Use Lia, lia@example.invalid e uma mensagem fictícia. O domínio invalid é reservado para exemplos e não serve como destino de e-mail. Este formulário não envia e-mail nem cria cadastro.
Faça no seu exemplo
Localize o campo de nome no formulário.
<label for="nome">Nome fictício</label>
<input id="nome" name="nome" required maxlength="80">
Mude uma coisa e preveja
Troque somente o texto do rótulo para Personagem do exercício.
Anote o que você acha que vai acontecer antes de salvar e recarregar.
Recarregue e confira
Recarregue e clique no rótulo. O cursor deve continuar entrando no mesmo campo. O PHP ainda recebe a chave nome.
Se não acontecer
Se o clique não focar, compare for e id. Não troque name só para mudar o texto visível do rótulo.
Execute o bloco só no envio
O bloco de leitura confere o método antes de tratar o formulário. Abrir a página produz GET e não entra nesse bloco. Pressionar Enviar para conferência produz POST.
Campo lê nome, email e mensagem de $_POST. Depois a resposta mostra a mensagem recebida com escapar. Até esta etapa não existe gravação no disco: recarregar uma nova abertura limpa os campos.
O formulário usa a validação básica do navegador para orientar o preenchimento. Ela será complementada no servidor antes da primeira gravação. A ferramenta do navegador e o programa no servidor fazem verificações em momentos diferentes.
Faça no seu exemplo
No início de public/index.php, confira a condição e a leitura de mensagem.
if (($_SERVER["REQUEST_METHOD"] ?? "") === "POST") {
$valores["mensagem"] = campo($_POST, "mensagem");
}
Mude uma coisa e preveja
Preencha os três campos fictícios e mude somente a mensagem para Esta mensagem chegou ao PHP local.
Anote o que você acha que vai acontecer antes de salvar e recarregar.
Recarregue e confira
Envie. A resposta deve mostrar a mensagem como texto e informar Recebido para conferência. Nada foi gravado.
Se não acontecer
Se a mensagem ficar vazia, confira name=“mensagem” e a chave no PHP. Se o navegador tentar abrir outro arquivo, confira action e a pasta public do teste.
Preserve o que foi digitado na resposta
Depois de um POST, a página é construída de novo. Para manter o valor no formulário, a resposta precisa usar os valores que acabou de ler. Input usa value; textarea usa conteúdo entre abertura e fechamento.
Os valores são preparados com escapar antes de entrar no HTML. Isso vale também para as aspas do atributo value. Alterar só o texto visível não autoriza o programa a misturar dados com marcação.
Pressionar Limpar restaura os valores iniciais presentes nessa resposta. Após um envio, esses valores podem ser os reapresentados pelo servidor. Para abrir um formulário novo e vazio, use o link Novo formulário. Não confunda reset do HTML com apagar um arquivo gravado.
Faça no seu exemplo
Confira a saída entre as tags do textarea.
<textarea id="mensagem" name="mensagem" required
maxlength="1000" rows="4"><?= escapar($valores["mensagem"]) ?></textarea>
Mude uma coisa e preveja
Envie uma mensagem fictícia com uma quebra de linha.
Anote o que você acha que vai acontecer antes de salvar e recarregar.
Recarregue e confira
As duas linhas devem continuar no campo e na confirmação. Abra Novo formulário e confira que a nova abertura está vazia.
Se não acontecer
Se value no textarea não funcionar, coloque o texto entre as tags. Se os sinais virarem HTML, confira escapar na saída.

A captura mostra um trecho da referência concluída. Abra e percorra o exemplo para conferir o restante. Experimentos temporários podem produzir outra aparência; restaure os valores indicados antes de comparar.
Atividades para fazer antes das respostas
Use uma nova cópia do exemplo. Tente aplicar o que aprendeu antes de consultar os comentários.
-
Mude o rótulo sem mudar a chave recebida.
-
Envie texto contendo teste.
-
Abra Novo formulário após conferir uma mensagem.
Respostas comentadas
Compare sua explicação e o que realmente aconteceu. Outra solução pode funcionar se cumprir o objetivo e preservar o acesso ao conteúdo.
-
Altere o conteúdo de label; preserve name, for e id.
-
O texto deve continuar literal, sem virar negrito.
-
O link abre index.php por GET. Os campos voltam vazios e não havia arquivo para apagar.
Quando seguir
Você reconhece o caminho do campo até $_POST e a reapresentação da resposta. Se ainda precisa de ajuda, repita a experiência pequena antes de avançar.
Consulta opcional
Não é preciso ler os links externos para executar os arquivos fornecidos. Eles servem para consultar detalhes quando você quiser.
O arquivo completo
Referência do exemplo 13-formulario-post, reproduzida aqui para que você possa conferir sem sair da página.
apoio.php
<?php
declare(strict_types=1);
function escapar(string $texto): string
{
return htmlspecialchars($texto, ENT_QUOTES | ENT_SUBSTITUTE, "UTF-8");
}
function campo(array $dados, string $chave): string
{
$valor = $dados[$chave] ?? "";
if (!is_string($valor) || preg_match('//u', $valor) !== 1) {
return "";
}
return trim($valor);
}
function tamanho(string $texto): int
{
if (function_exists("mb_strlen")) {
return mb_strlen($texto, "UTF-8");
}
return preg_match_all('/./us', $texto);
}
public/estilos.css
* { box-sizing: border-box; }
body { margin: 0; background: #f4f7fb; color: #203246;
font: 1.05rem/1.65 Arial, sans-serif; }
header, main, footer { max-width: 48rem; margin-inline: auto; padding: 1.5rem; }
header { padding-top: 2.5rem; }
h1 { font-size: clamp(1.8rem, 5vw, 2.7rem); line-height: 1.2; }
main { background: #fff; border-radius: .8rem; }
article { border-top: 1px solid #cad4df; padding-block: 1rem; }
a { color: #124e77; text-underline-offset: .2em; }
nav { display: flex; flex-wrap: wrap; gap: 1rem; }
label { display: block; font-weight: bold; }
input:not([type=hidden]), textarea { width: 100%; max-width: 34rem;
border: 2px solid #718095; border-radius: .35rem; padding: .7rem;
font: inherit; color: inherit; background: #fff; }
button { font: inherit; background: #124e77; color: white;
border: 0; border-radius: .35rem; padding: .75rem 1.2rem; cursor: pointer; }
button:hover { background: #103b59; }
.mensagem { white-space: pre-wrap; overflow-wrap: anywhere; }
.erros { color: #8b142c; }
.ok { color: #175c30; font-weight: bold; }
:focus-visible { outline: 3px solid #b04d00; outline-offset: 3px; }
.pular { position: absolute; left: -10000px; }
.pular:focus { position: static; display: block; padding: 1rem; background: white; }
@media (max-width: 35rem) { header,main,footer { padding: 1rem; } }