Processamento de Formulários PHP: Um Guia Completo
Aprenda a processar formulários PHP com validação, segurança contra XSS e SQL injection, e como manter os campos preenchidos após erros.
Lidar com formulários é uma das tarefas mais comuns em qualquer aplicação web: uma página de cadastro, um formulário de contato, uma caixa de busca ou um fluxo de checkout enviam dados do usuário ao servidor, onde PHP os lê, verifica e processa. Este guia percorre todo o ciclo — do formulário HTML no navegador ao PHP que recebe, valida e reutiliza com segurança os dados enviados.
Ao final, você entenderá como $_POST e $_GET funcionam, como validar dados no servidor, como manter o formulário "persistente" após um erro e como evitar as duas falhas clássicas de segurança (XSS e SQL injection).
Como funciona o envio de um formulário
O envio de um formulário é uma única requisição HTTP do navegador ao servidor:
- O usuário preenche os campos e clica em Enviar.
- O navegador empacota os valores dos campos de acordo com o
methoddo formulário e os envia para a URL definida emaction. - O PHP no servidor recebe os valores em um array superglobal —
$_POSTou$_GET— e seu script os processa.
Como os dados vêm do navegador do usuário, você nunca pode confiar neles. Qualquer pessoa pode alterar valores de campos, remover campos ou enviar a requisição sem usar seu formulário. A validação no lado do servidor, portanto, não é opcional — os atributos required e type="email" do lado do cliente são apenas uma conveniência.
Criando um formulário HTML
Todo formulário começa em HTML. O formulário contém campos de entrada — caixas de texto, campos de e-mail, botões de rádio, checkboxes — e um botão de envio. Dois atributos controlam tudo:
action— a URL que recebe os dados (omita para enviar de volta à mesma página).method—postouget(veja a comparação abaixo).
<form action="form_processing.php" method="post">
<p>
<label for="name">Name:</label>
<input type="text" id="name" name="name" />
</p>
<p>
<label for="email">Email:</label>
<input type="email" id="email" name="email" />
</p>
<input type="submit" value="Submit" />
</form>O atributo name de cada campo é a chave que você lê no servidor: name="email" torna-se $_POST['email']. Um campo sem name nunca é enviado. Sempre associe cada campo a um <label> por questões de acessibilidade.
POST vs. GET
O atributo method decide como os dados trafegam e qual array os recebe.
method="post" | method="get" | |
|---|---|---|
| Localização dos dados | Corpo da requisição HTTP | Anexados à URL como query string |
| Array PHP | $_POST | $_GET |
| Visível na URL | Não | Sim (?name=Ann&email=...) |
| Pode ser salvo como favorito / compartilhado | Não | Sim |
| Indicado para | Senhas, qualquer coisa que altere dados | Filtros de busca, paginação — requisições somente leitura |
Use POST para qualquer coisa que crie, atualize ou exclua dados, ou que contenha valores sensíveis. Use GET para buscas e filtros que você quer que os usuários possam salvar como favorito. Ambos chegam no superglobal correspondente; o restante deste guia usa POST.
Lendo os dados enviados
Quando o formulário é enviado, o PHP preenche $_POST com os nomes dos campos como chaves e o texto enviado como valores. Leia cada campo, mas proteja-se contra chaves ausentes com o operador de coalescência nula ?? para que um campo ausente retorne uma string vazia em vez de um aviso:
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';Verifique $_SERVER['REQUEST_METHOD'] para que o código de processamento só seja executado em um envio real, e não quando a página é aberta pela primeira vez:
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
// ...validate and use the values
}Validando os dados
A validação responde a uma pergunta: este valor é aceitável? Colete todos os problemas em um array $errors para poder mostrar ao usuário todos os erros de uma vez, em vez de parar no primeiro. Use filter_var() com FILTER_VALIDATE_EMAIL para verificar o formato do e-mail corretamente:
$errors = [];
if (trim($name) === '') {
$errors[] = "Name is required";
}
if (trim($email) === '') {
$errors[] = "Email is required";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "Invalid email format";
}
if (!empty($errors)) {
foreach ($errors as $error) {
echo htmlspecialchars($error) . "<br>";
}
}Usamos trim() para que um campo contendo apenas espaços ainda seja considerado vazio, e depois filter_var() para confirmar que o e-mail tem o formato [email protected]. Se $errors não estiver vazio, as mensagens são exibidas; caso contrário, os dados estão limpos e prontos para uso. Para uma cobertura mais aprofundada de campos obrigatórios e regras de e-mail/URL, consulte validação de formulários PHP e validação de campos obrigatórios.
Escapando a saída: prevenindo XSS
Observe a chamada a htmlspecialchars() acima. Sempre que você exibir um valor que veio do usuário, deve escapá-lo, ou um invasor pode enviar tags <script> que executarão nos navegadores de outros visitantes — um ataque de cross-site scripting (XSS). htmlspecialchars() converte <, >, & e aspas em entidades HTML inofensivas:
$dangerous = '<script>alert("xss")</script>';
echo htmlspecialchars($dangerous);
// <script>alert("xss")</script>O navegador agora exibe o texto literalmente em vez de executá-lo. Escape na saída, sempre.
Mantendo o formulário persistente
Se a validação falhar, reexiba o formulário com os valores do usuário ainda preenchidos — redigitar tudo é frustrante. Devolva cada valor para seu atributo value, escapado:
<input
type="text"
name="name"
value="<?php echo htmlspecialchars($name ?? ''); ?>"
/>Como a mesma página tanto renderiza o formulário quanto o processa, defina action="" (enviar de volta para si mesma) e o campo é preenchido automaticamente após um envio com falha.
Juntando tudo
Aqui está uma página de autoprocessamento que renderiza o formulário, valida no POST, exibe erros, mantém o formulário persistente e confirma o sucesso — o padrão que a maioria dos formulários de contato reais segue:
<?php
$name = $email = '';
$errors = [];
$success = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
if ($name === '') {
$errors[] = 'Name is required';
}
if ($email === '') {
$errors[] = 'Email is required';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Invalid email format';
}
if (!$errors) {
$success = true; // here you would save to a database or send an email
}
}
?>
<?php if ($success): ?>
<p>Thanks, <?php echo htmlspecialchars($name); ?>!</p>
<?php else: ?>
<?php foreach ($errors as $e): ?>
<p style="color:red"><?php echo htmlspecialchars($e); ?></p>
<?php endforeach; ?>
<form action="" method="post">
Name:
<input type="text" name="name"
value="<?php echo htmlspecialchars($name); ?>"><br>
Email:
<input type="email" name="email"
value="<?php echo htmlspecialchars($email); ?>"><br>
<input type="submit" value="Submit">
</form>
<?php endif; ?>Armazenando dados com segurança: prevenindo SQL injection
Depois que os dados são válidos, frequentemente você os salva em um banco de dados. Nunca insira dados do usuário diretamente em uma string SQL — isso abre a porta para SQL injection. Use uma instrução preparada para que o banco de dados trate os valores como dados, nunca como comandos:
$mysqli = new mysqli('localhost', 'user', 'pass', 'app');
$stmt = $mysqli->prepare(
'INSERT INTO contacts (name, email) VALUES (?, ?)'
);
$stmt->bind_param('ss', $name, $email);
$stmt->execute();Os marcadores ? e bind_param() mantêm os valores separados da consulta, para que uma entrada como '; DROP TABLE contacts; -- seja armazenada como texto inofensivo em vez de ser executada.
Lista de verificação de segurança
Um script de processamento de formulário seguro segue uma rotina curta e repetível:
- Valide todos os campos no servidor — nunca confie apenas nas verificações do navegador.
- Escape na saída com
htmlspecialchars()para evitar XSS. - Use instruções preparadas para todas as consultas ao banco de dados para evitar SQL injection.
- Hash de senhas com
password_hash()antes de armazená-las — nunca armazene texto puro. - Adicione um token CSRF a formulários que alteram estado para que requisições não possam ser forjadas de outros sites.
- Adicione CAPTCHA a formulários públicos para reduzir envios automáticos de spam.
Capítulos relacionados
- Manipulação de formulários PHP — os fundamentos de recepção de dados de formulário.
- PHP $_POST — o superglobal em profundidade.
- Validação de formulários PHP — padrões completos de validação.
- Superglobais PHP —
$_POST,$_GET,$_SERVERe mais.