W3docs

Validação de Formulários PHP

A validação de formulários é essencial no desenvolvimento web, garantindo que os dados inseridos pelos utilizadores sejam precisos e completos antes de serem processados com PHP.

A validação de formulários é o processo de verificar se os dados enviados por um utilizador através de um formulário HTML estão presentes, corretamente formatados e seguros para uso antes de o script processá-los. Em PHP, a validação é executada no servidor após o envio do formulário, por isso não pode ser contornada desativando JavaScript ou enviando uma solicitação diretamente.

Este capítulo aborda o fluxo completo de validação: por que a validação no lado do servidor é importante, a diferença entre sanitizar e validar, as funções PHP que serão utilizadas, e um exemplo completo e seguro que pode ser adaptado. Se você é novo no recebimento de dados de formulários, leia primeiro Tratamento de Formulários PHP.

Por que a Validação no Lado do Servidor É Importante

A validação no lado do cliente (HTML5 required, type="email", JavaScript) melhora a experiência do utilizador ao capturar erros instantaneamente — mas é apenas uma conveniência. Um utilizador determinado ou malicioso pode desativar o JavaScript ou enviar uma solicitação HTTP elaborada que ignora completamente o navegador. O servidor é o único lugar onde a validação pode ser confiável. A validação PHP no lado do servidor permite:

  • Garantir que os campos obrigatórios estejam realmente presentes e não vazios.
  • Confirmar que os valores correspondem ao formato esperado (um e-mail real, um número dentro do intervalo).
  • Neutralizar entradas perigosas antes que cheguem a um banco de dados ou a uma página HTML, prevenindo SQL injection e cross-site scripting (XSS).

Trate cada valor em $_POST, $_GET e $_REQUEST como não confiável até que tenha sido verificado. Esses arrays vêm das superglobais do PHP.

Sanitizar vs. Validar

Esses dois termos são frequentemente confundidos, mas desempenham funções diferentes:

  • Sanitizar limpa um valor — remove ou escapa caracteres indesejados. trim() remove espaços em branco ao redor; htmlspecialchars() converte <, >, & e aspas em entidades HTML para que sejam renderizados como texto em vez de serem executados.
  • Validar verifica um valor contra uma regra e informa aprovação ou reprovação — não altera o valor. filter_var($email, FILTER_VALIDATE_EMAIL) retorna o e-mail se parecer válido, ou false caso contrário.

Um fluxo típico é: sanitizar primeiro (remover espaços em branco), depois validar, e por fim escapar na saída (ao ecoar de volta para HTML). Para uma cobertura mais aprofundada do sistema de filtragem do PHP, veja Filtros PHP e filter_var().

Etapas de Validação

Uma rotina de validação no lado do servidor geralmente segue as mesmas quatro etapas:

  1. Construir o formulário HTML e apontar seu action para o script PHP.
  2. Detectar um envio POST com $_SERVER["REQUEST_METHOD"].
  3. Para cada campo: ler o valor, sanitizá-lo, depois validá-lo — coletando mensagens de erro.
  4. Se todos os campos passarem, processar os dados; caso contrário, renderizar novamente o formulário com as mensagens de erro e os valores que o utilizador já digitou.

Funções PHP de Validação Úteis

FunçãoFinalidade
trim()Remove espaços em branco do início e do fim de uma string.
empty()Verifica se um valor está ausente ou é uma string vazia.
filter_var()Valida ou sanitiza usando um filtro embutido (ex.: FILTER_VALIDATE_EMAIL, FILTER_VALIDATE_INT).
is_numeric()Retorna true se o valor for um número ou string numérica.
htmlspecialchars()Escapa caracteres especiais HTML para prevenir XSS na saída.
preg_match()Valida contra um padrão de expressão regular personalizado.

Um Exemplo Mínimo

Antes do exemplo completo com banco de dados abaixo, aqui está a validação mais simples que captura o padrão principal — sanitizar, depois validar, depois coletar erros:

<?php
$email = trim($_POST["email"] ?? "");
$errors = [];

if ($email === "") {
    $errors["email"] = "Please enter your email.";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    $errors["email"] = "Please enter a valid email address.";
}

if (empty($errors)) {
    echo "Valid email: " . htmlspecialchars($email);
} else {
    echo $errors["email"];
}
?>

Se $_POST["email"] for " [email protected] ", os espaços ao redor são removidos, o valor é validado e o script exibe Valid email: [email protected]. Uma entrada como "not-an-email" produz Please enter a valid email address.

Exemplo Completo: Validando e Armazenando um Formulário

O exemplo abaixo valida um nome, e-mail, gênero e comentário, e depois insere a linha usando uma prepared statement — a abordagem de prepared statement (com mysqli) é o que protege contra SQL injection, pois a entrada do utilizador é enviada separadamente do texto SQL e nunca é interpretada como código.

Atualize as credenciais do banco de dados e certifique-se de que seu banco de dados contenha uma tabela users com colunas name, email, gender e comment antes de executar este exemplo.

<?php
// Database connection setup
$link = mysqli_connect("localhost", "username", "password", "database");
if (!$link) {
    die("Connection failed: " . mysqli_connect_error());
}

// Define variables and initialize with empty values
$name = $email = $gender = $comment = $website = "";
$name_err = $email_err = $gender_err = $comment_err = "";
 
// Processing form data when form is submitted
if($_SERVER["REQUEST_METHOD"] == "POST"){
    // Validate name
    if(empty(trim($_POST["name"] ?? ""))){
        $name_err = "Please enter your name.";
    } else{
        $name = trim($_POST["name"]);
    }
    
    // Validate email
    if(empty(trim($_POST["email"] ?? ""))){
        $email_err = "Please enter your email.";
    } elseif(!filter_var(trim($_POST["email"] ?? ""), FILTER_VALIDATE_EMAIL)) {
        $email_err = "Please enter a valid email address.";
    } else{
        $email = trim($_POST["email"]);
    }
    
    // Validate gender
    if(!isset($_POST["gender"]) || empty($_POST["gender"])){
        $gender_err = "Please select your gender.";
    } else{
        $gender = $_POST["gender"];
    }
    
    // Validate comment
    if(empty(trim($_POST["comment"] ?? ""))){
        $comment_err = "Please enter your comment.";
    } else{
        $comment = trim($_POST["comment"]);
    }
    
    // Check input errors before inserting in database
    if(empty($name_err) && empty($email_err) && empty($gender_err) && empty($comment_err)){
        // Prepare an insert statement
        $sql = "INSERT INTO users (name, email, gender, comment) VALUES (?, ?, ?, ?)";
         
        if($stmt = mysqli_prepare($link, $sql)){
            // Bind variables to the prepared statement as parameters
            mysqli_stmt_bind_param($stmt, "ssss", $param_name, $param_email, $param_gender, $param_comment);
            
            // Set parameters
            $param_name = $name;
            $param_email = $email;
            $param_gender = $gender;
            $param_comment = $comment;
            
            // Attempt to execute the prepared statement
            if(mysqli_stmt_execute($stmt)){
                // Records created successfully. Redirect to landing page
                header("location: index.php");
                exit();
            } else{
                echo "Something went wrong. Please try again later.";
            }
        }
         
        // Close statement
        mysqli_stmt_close($stmt);
    }
}

// Close connection
mysqli_close($link);
?>
<!DOCTYPE html>
<html>
<head><title>PHP Form Validation</title></head>
<body>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
    Name: <input type="text" name="name" value="<?php echo htmlspecialchars($name); ?>">
    <span class="error"><?php echo $name_err; ?></span><br><br>
    Email: <input type="text" name="email" value="<?php echo htmlspecialchars($email); ?>">
    <span class="error"><?php echo $email_err; ?></span><br><br>
    Gender:
    <input type="radio" name="gender" value="female"> Female
    <input type="radio" name="gender" value="male"> Male
    <span class="error"><?php echo $gender_err; ?></span><br><br>
    Comment: <textarea name="comment"><?php echo htmlspecialchars($comment); ?></textarea>
    <span class="error"><?php echo $comment_err; ?></span><br><br>
    <input type="submit" value="Submit">
</form>
</body>
</html>

Exibindo Erros e Mantendo a Entrada do Utilizador

Observe três detalhes no exemplo que proporcionam uma boa UX para formulários:

  • Cada variável de erro ($name_err, $email_err, …) é exibida em um <span class="error"> ao lado do seu campo, para que o utilizador saiba exatamente qual entrada corrigir.
  • O action do formulário echoa htmlspecialchars($_SERVER["PHP_SELF"]). Sem o escape, PHP_SELF pode ser explorado para injetar scripts através da URL, portanto escapá-lo é uma medida de segurança, não apenas de formatação.
  • Cada valor re-exibido no formulário é passado por htmlspecialchars(). Isso tanto previne XSS quanto permite que o utilizador mantenha o que já digitou, em vez de reinserir tudo depois de um campo inválido.

Problemas Comuns

  • empty() trata "0" como vazio. Um campo cujo valor é a string "0" falhará em uma verificação com empty(). Para campos onde 0 é válido, compare explicitamente: if ($value === "").
  • Valide antes de confiar no tipo. Os valores de $_POST são sempre strings. Use filter_var($n, FILTER_VALIDATE_INT) ou is_numeric() em vez de assumir que um número chegou.
  • Escape na saída, não no armazenamento. Armazene o valor bruto (validado) no banco de dados e aplique htmlspecialchars() apenas ao ecoar em HTML. Escapar antes do armazenamento corrompe os dados para usos não-HTML.
  • Use o operador null-coalescing. $_POST["x"] ?? "" evita avisos de "Undefined array key" quando um campo está ausente.

Validando Outros Tipos de Campo

O mesmo padrão se aplica a qualquer campo — apenas a regra de validação muda:

<?php
// Age: an integer between 18 and 120
$age = filter_var($_POST["age"] ?? "", FILTER_VALIDATE_INT, [
    "options" => ["min_range" => 18, "max_range" => 120],
]);
if ($age === false) {
    echo "Please enter an age between 18 and 120.";
}

// Username: 3-16 letters, digits, or underscores
$username = trim($_POST["username"] ?? "");
if (!preg_match('/^[A-Za-z0-9_]{3,16}$/', $username)) {
    echo "Username must be 3-16 letters, digits, or underscores.";
}
?>

Para regras específicas de URL e e-mail, veja URL e E-mail em Formulários PHP; para marcar campos como obrigatórios, veja Campos Obrigatórios em Formulários PHP; e para ver todas as peças reunidas, veja Formulário Completo PHP.

Conclusão

A validação no lado do servidor em PHP é o que torna um formulário confiável: confirma que os dados estão presentes e corretamente formatados, e — combinada com htmlspecialchars() na saída e prepared statements no armazenamento — bloqueia XSS e SQL injection. A receita básica é sempre a mesma: sanitizar, validar, coletar erros e renderizar novamente o formulário com mensagens úteis quando algo estiver errado. Domine esse ciclo e poderá validar qualquer campo simplesmente trocando a regra de validação.

Prática

Prática
Quais são alguns elementos-chave na validação de formulários PHP?
Quais são alguns elementos-chave na validação de formulários PHP?
Was this page helpful?