Como criar um formulário em PHP e armazenar os dados no MySQL

Sumário

Neste artigo, vamos criar um formulário simples usando HTML, CSS e PHP, com campos como Nome, Email e Mensagem, e aprender como armazenar esses dados em um banco de dados MySQL para uso futuro.

Ambiente de teste

Vou assumir que você já tenha um ambiente para executar o código, seja uma hospedagem ou um sistema como o XAMPP.

Estrutura do banco de dados

Para iniciar o projeto vamos criar um banco de dados chamado contato_formulario nele terá a tabela contatos com as colunas id, nome, email, mensagem e data_envio. Para fazer isso execute o seguinte SQL:

CREATE DATABASE contato_formulario;
USE contato_formulario;

CREATE TABLE contatos (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nome VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL,
    mensagem TEXT NOT NULL,
    data_envio TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

O id tem que ser do tipo AUTO_INCREMENT pois assim ele será gerado automaticamente a cada novo registro na tabela.

Estrutura dos arquivos

Crie os arquivos:

index.html : Página inicial onde ficara o código do formulário.

formulario.php : Aqui vamos adicionar o código PHP que irá receber os valores do formulário e inserir eles no banco de dados.

listar.php : Será respónsavel por listar os dados cadastrados no banco de dados.

db.php : Vai armazenar as credenciais de login do banco de dados.

style.css : Vai ter o código CSS que irá estilizar as páginas.

Conexão com o banco de dados (db.php)

Vamos usar a extensão PDO (PHP Data Objects) para fazer a conexão com o banco de dados:

<?php

$host = 'localhost';
$usuario = 'nome de usuário';
$senha = 'senha';
$banco = 'nome do banco de dados';

try {
    $conexao = new PDO("mysql:host=$host;dbname=$banco;charset=utf8", $usuario, $senha);
    $conexao->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    echo "Erro na conexão" . $e->getMessage();
    die();
}

?>

Começamos declarando as váriaveis que são responsáveis por armazenar as credenciais de login, faça a substituição das informações pelo seus dados (é importante ressaltar que em um ambiente de produção deve-se armazenar as credenciais em variáveis de ambiente).

O código dentro do try{} usa o new PDO para criar uma nova instância da classe PDO, nela definimos o servidor MySQL (mysql:host=$host;), o banco de dados a ser acessado (dbname=$banco;) e o conjunto de caracteres a ser usado (charset=utf8;).

Se acontecer algum erro o código em catch{} exibe a mensagem do erro e usa o die() para encerrar a execução do script.

Estrutura do arquivo index.html

O seguinte código cria um formulário com 3 campos (Nome, Email e Mensagem), os dados serão enviados usando o método POST para o arquivo formulario.php onde serão processados e armazenados no banco de dados.

<!DOCTYPE HTML>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Formulário de Contato</title>
        <link rel="stylesheet" href="/style.css">
    </head>
    <body>
        <div class="formulario">
            <form action="formulario.php" method="post">
                <label for="nome">Nome</label>
                <input type="text" id="nome" name="nome">
                
                <label for="email">E-mail</label>
                <input type="email" id="email" name="email">
                
                <label for="mensagem">Mensagem</label>
                <textarea rows="4" name="mensagem"></textarea>
                
                <input type="submit" value="Enviar">
            </form>
        </div>
    </body>
</html>
Imagem do formulário feito com HTML e CSS
Imagem do formulário feito com HTML e CSS

Recebendo os dados e inserindo no banco de dados (formulario.php)

Os dados são enviados do index.html para o formulario.php usando o atributo name, onde será recebido pela variável superglobal $_POST que irá sanitizar os dados usando a função trim() para remover os espaços em branco extras e com a função htmlspecialchars() que converte caracteres especiais em entidades HTML, evitando assim ataques XSS. As informações são inseridas na tabela contatos por meio de prepared statements com bindParam(), para evitar SQL Injection.

<!DOCTYPE HTML>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Formulário de Contato</title>
        <link rel="stylesheet" href="/style.css">
    </head>
    <body>
        <?php
        
        // Inclui o arquivo de configuração do banco
        require_once 'db.php';

        // Recebe os dados com sanitização
        $nome = trim($_POST["nome"] ?? '');
        $email = trim($_POST["email"] ?? '');
        $mensagem = trim($_POST["mensagem"] ?? '');

        // Valida e-mail
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            die("E-mail inválido!");
        }

        // Proteção contra XSS
        $nome = htmlspecialchars($nome, ENT_QUOTES, 'UTF-8');
        $mensagem = htmlspecialchars($mensagem, ENT_QUOTES, 'UTF-8');

        // Inserção com Prepared Statements
        $stmt = $conexao->prepare("INSERT INTO contatos (nome, email, mensagem) VALUES (:nome, :email, :mensagem)");
        $stmt->bindParam(':nome', $nome);
        $stmt->bindParam(':email', $email);
        $stmt->bindParam(':mensagem', $mensagem);

        if ($stmt->execute()) {
            echo "<div class='dados'>";
            echo "<p>Dados inseridos com sucesso!</p>";
            echo "<a href='listar.php'>Ver todos os dados</a>";
            echo "</div>";
        } else {
            echo "Erro ao inserir dados!";
        }
        
        ?>
    </body>
</html>

Irá aparecer uma mensagem de sucesso junto com um link para visualizar os registros quando os dados forem inseridos na tabela contatos.

Imagem mostrando que os dados foram inseridos com sucesso!

Listando as informações do banco de dados (listar.php)

A consulta SELECT * FROM contatos irá retornar todos os registros da tabela e a função fetchAll(PDO::FETCH_ASSOC) vai transforma os resultados em um array associativo, onde cada chave representa o nome da coluna (exemplo: $contato['nome']). Usamos o if ($contatos) para verificar se existe registros no banco de dados, caso exista será feito um loop foreach para criar dinamicamente uma tabela HTML para listar as informações, caso não exista nenhum registro a mensagem "Nenhum dado encontrado!" será exibida.

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width">
    <title>Formulário de Contato</title>
    <link rel="stylesheet" href="/style.css">
</head>
<body>
    <div class="container-lista">
        <?php
        // Inclui o arquivo de configuração do banco
        require_once 'db.php';

        // Consulta para buscar todos os dados
        $stmt = $conexao->query("SELECT * FROM contatos");
        $contatos = $stmt->fetchAll(PDO::FETCH_ASSOC);

        if ($contatos) {
            echo "<h1>Todos os Contatos</h1>";
            echo "<table border='1'>
                    <tr>
                        <th>Nome</th>
                        <th>Email</th>
                        <th>Mensagem</th>
                    </tr>";
            
            foreach ($contatos as $contato) {
                echo "<tr>
                        <td>" . htmlspecialchars($contato['nome'], ENT_QUOTES, 'UTF-8') . "</td>
                        <td>" . htmlspecialchars($contato['email'], ENT_QUOTES, 'UTF-8') . "</td>
                        <td>" . htmlspecialchars($contato['mensagem'], ENT_QUOTES, 'UTF-8') . "</td>
                      </tr>";
            }
            
            echo "</table>";
        } else {
            echo "Nenhum dado encontrado!";
        }
        ?>
    </div>
</body>
</html>
Imagem mostrando os registros do banco de dados
Imagem mostrando os registros do banco de dados

Estilizando as páginas (style.css)

O seguinte código CSS vai estilizar as páginas, altere as cores e layout como preferir.

/* Reset básico */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* Corpo da página */
body {
    font-family: Arial, sans-serif;
    background-color: #f9f9f9;  /* Fundo cinza claro */
    color: #333;  /* Texto preto escuro */
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    min-height: 100vh;  /* Ocupa toda a altura da tela */
    margin: 0;
}

/* Container principal */
.container {
    background-color: white;
    padding: 30px;
    border-radius: 8px;
    box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
    width: 100%;
    max-width: 800px;  /* Largura máxima para dispositivos maiores */
    text-align: center;
}

.dados {
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* Título */
h1 {
    color: #000;
    font-size: 24px;
    margin-bottom: 20px;
    text-align: center;
}

.formulario {
    padding: 30px;
    border-radius: 10px;
    border: 1px solid #000000;
}

/* Formulário */
form {
    display: flex;
    flex-direction: column;
    gap: 15px;
    width: 400px;
}

/* Labels e Inputs */
label {
    text-align: left;
    font-weight: bold;
    color: #333;
}

input[type="text"], input[type="email"], textarea {
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 4px;
    font-size: 14px;
    width: 100%;
}

textarea {
    resize: vertical; /* Permite que o usuário redimensione verticalmente */
}

/* Botão de envio */
input[type="submit"] {
    background-color: #000;
    color: #fff;
    padding: 10px 20px;
    border: none;
    border-radius: 4px;
    font-size: 16px;
    cursor: pointer;
    transition: background-color 0.3s;
}

input[type="submit"]:hover {
    background-color: #444;
}

/* Tabela de contatos */
table {
    width: 100%;
    margin-top: 20px;
    border-collapse: collapse;
}

th, td {
    padding: 10px;
    border: 1px solid #ddd;
}

th {
    background-color: #000;
    color: #fff;
    text-align: left;
}

td {
    background-color: #f9f9f9;
}


a {
    display: block;
    margin-top: 20px;
    color: #000;
    font-size: 16px;
    text-decoration: none;
    padding: 10px;
    border: 1px solid #000;
    border-radius: 4px;
    background-color: #fff;
    transition: background-color 0.3s, color 0.3s;
}

a:hover {
    background-color: #000;
    color: #fff;
}

Se você tiver alguma dúvida fique a vontade para comentar. Até o próximo artigo!!

Gostou? Compartilhe

Facebook
X
LinkedIn
Telegram
WhatsApp
Email

Continue Aprendendo: Veja Também Estes Artigos!

Nenhum artigo relacionado foi encontrado!

Tem dúvidas ou sugestões?

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *