W3docs

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:

  1. O usuário preenche os campos e clica em Enviar.
  2. O navegador empacota os valores dos campos de acordo com o method do formulário e os envia para a URL definida em action.
  3. O PHP no servidor recebe os valores em um array superglobal$_POST ou $_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).
  • methodpost ou get (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 dadosCorpo da requisição HTTPAnexados à URL como query string
Array PHP$_POST$_GET
Visível na URLNãoSim (?name=Ann&email=...)
Pode ser salvo como favorito / compartilhadoNãoSim
Indicado paraSenhas, qualquer coisa que altere dadosFiltros 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);
// &lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;

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

Prática

Prática
O que $_POST faz em PHP?
O que $_POST faz em PHP?
Was this page helpful?