PHP AJAX Poll
Aprenda a criar uma enquete AJAX em PHP que registra votos e exibe resultados ao vivo sem recarregar a página, usando fetch, JSON e MySQL.
O que é uma Enquete AJAX?
Uma enquete AJAX é um pequeno widget de votação que permite ao usuário escolher uma opção, envia esse voto ao servidor em segundo plano e exibe os resultados atualizados — tudo sem recarregar a página. AJAX (Asynchronous JavaScript and XML) é a técnica de trocar dados com o servidor usando JavaScript após a página já ter sido carregada.
Este capítulo constrói uma enquete completa: uma tabela MySQL para armazenar as opções e suas contagens de votos, um script PHP que registra um voto e retorna a contagem atual como JSON, e uma pequena quantidade de JavaScript que envia o voto e renderiza os resultados.
Se você quiser atualizar continuamente os dados em um temporizador (um placar ao vivo, um painel de status), os mesmos blocos de construção se aplicam — esse padrão é chamado de polling, e o abordamos ao final do capítulo.
Por que Usar AJAX para uma Enquete?
- Sem recarga de página. O usuário permanece na página; apenas a área da enquete muda. Isso parece instantâneo e mantém o restante da página (posição de rolagem, vídeo, campos de formulário) intacto.
- Menos dados transferidos. Em vez de reenviar o documento HTML inteiro, o servidor retorna apenas as contagens de votos como um pequeno payload JSON.
- Resultados ao vivo. Como a resposta é dados, não marcação, você pode re-renderizar uma barra de resultados imediatamente e até atualizá-la em um temporizador para refletir votos de outros usuários.
Passo 1 — Criar a Tabela no Banco de Dados
Cada opção da enquete é uma linha. Armazenamos o texto da opção e um contador de votos em execução.
CREATE TABLE poll_options (
id INT AUTO_INCREMENT PRIMARY KEY,
option_text VARCHAR(100) NOT NULL,
votes INT NOT NULL DEFAULT 0
);
INSERT INTO poll_options (option_text) VALUES
('PHP'),
('JavaScript'),
('Python');Se você é novo na criação de tabelas, consulte Criar uma Tabela MySQL e Inserir Dados.
Passo 2 — Construir o Formulário HTML
O formulário lista as opções como botões de rádio e reserva um contêiner para os resultados.
<form id="pollForm">
<p>What is your favorite language?</p>
<label><input type="radio" name="option" value="1"> PHP</label>
<label><input type="radio" name="option" value="2"> JavaScript</label>
<label><input type="radio" name="option" value="3"> Python</label>
<button type="submit">Vote</button>
</form>
<div id="pollResults"></div>O value de cada botão de rádio é o id da opção no banco de dados — isso é a única coisa que precisamos enviar ao servidor.
Passo 3 — Escrever o Handler PHP
O script PHP faz dois trabalhos: registrar um voto (quando um é enviado) e retornar os resultados atuais como JSON. Sempre use prepared statements para que um valor vindo do navegador nunca possa ser interpretado como SQL.
<?php
header('Content-Type: application/json');
$dsn = "mysql:host=localhost;dbname=your_database;charset=utf8mb4";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
try {
$pdo = new PDO($dsn, 'username', 'password', $options);
// If a vote was submitted, increment that option's counter.
if (isset($_POST['option'])) {
$optionId = (int) $_POST['option'];
$update = $pdo->prepare(
"UPDATE poll_options SET votes = votes + 1 WHERE id = :id"
);
$update->execute([':id' => $optionId]);
}
// Always return the current tally.
$rows = $pdo->query(
"SELECT id, option_text, votes FROM poll_options ORDER BY id"
)->fetchAll();
$total = array_sum(array_column($rows, 'votes'));
echo json_encode([
'status' => 'success',
'total' => $total,
'options' => $rows,
]);
} catch (PDOException $e) {
http_response_code(500);
echo json_encode(['status' => 'error', 'message' => 'Database error']);
}Converter o id recebido com (int) e vinculá-lo com :id significa que o valor é tratado estritamente como um número, não como parte da consulta. Para mais informações, leia PHP Prepared Statements e json_encode().
Passo 4 — Enviar o Voto com JavaScript
Interceptamos o evento submit do formulário, enviamos a opção selecionada com fetch() e, em seguida, desenhamos uma barra de resultados a partir da resposta JSON.
const form = document.getElementById('pollForm');
const resultsBox = document.getElementById('pollResults');
form.addEventListener('submit', function (event) {
event.preventDefault(); // Stop the normal page reload.
const selected = form.querySelector('input[name="option"]:checked');
if (!selected) return; // Nothing chosen yet.
const body = new URLSearchParams({ option: selected.value });
fetch('poll.php', { method: 'POST', body })
.then(response => response.json())
.then(showResults)
.catch(error => console.error('Vote failed:', error));
});
function showResults(data) {
if (data.status !== 'success') {
resultsBox.textContent = 'Could not load results.';
return;
}
resultsBox.innerHTML = data.options.map(opt => {
const percent = data.total
? Math.round((opt.votes / data.total) * 100)
: 0;
return `<div>${opt.option_text}: ${opt.votes} votes (${percent}%)</div>`;
}).join('');
}event.preventDefault() é o que impede o navegador de fazer um envio completo, que é o ponto central do AJAX. A porcentagem é calculada no cliente a partir das contagens que o servidor retornou, então a barra sempre corresponde aos dados mais recentes.
Passo 5 — Manter os Resultados ao Vivo com Polling
Até agora, os resultados são atualizados apenas quando este usuário vota. Para refletir votos de outros usuários, faça polling no servidor em um temporizador — solicite a contagem mais recente a cada poucos segundos e re-renderize:
function refreshResults() {
fetch('poll.php') // GET, no vote — just read the tally.
.then(response => response.json())
.then(showResults)
.catch(error => console.error('Refresh failed:', error));
}
setInterval(refreshResults, 5000); // Every 5 seconds.Como o handler PHP retorna a contagem em cada solicitação (voto ou não), um GET simples é suficiente para buscar números atualizados. Escolha o intervalo com cuidado: um intervalo curto parece mais ao vivo, mas cria mais solicitações. Para dados que precisam ser verdadeiramente em tempo real, WebSockets ou Server-Sent Events são mais adequados do que polling de intervalo fixo.
Erros Comuns
- Esquecer
event.preventDefault(). Sem isso, o formulário recarrega a página e a chamada AJAX é cancelada no meio do caminho. - Confiar no id da opção. Sempre converta/valide-o e use um prepared statement; nunca concatene
$_POSTno SQL. - Contagem duplicada. Este exemplo básico permite que um navegador vote várias vezes. Em produção, restrinja por sessão, cookie ou IP.
- Polling muito agressivo. Um intervalo de um segundo em uma página movimentada pode sobrecarregar o servidor; 3–10 segundos geralmente é suficiente.
Resumo
Uma enquete AJAX combina uma tabela MySQL, um endpoint PHP que registra um voto e retorna a contagem como JSON, e JavaScript que envia com fetch() e renderiza os resultados — sem recarga de página. Adicione um poll com setInterval para manter os números ao vivo para todos.
graph TD;
A(User Selects Option and Clicks Vote) --> B(JavaScript Sends POST with fetch);
B --> C(PHP Increments Vote with Prepared Statement);
C --> D(PHP Returns Tally as JSON);
D --> E(JavaScript Renders Results Bar);
F(Timer Every 5s) --> G(GET poll.php for Latest Tally);
G --> D;