Разработка опроса на языке PHP: обработка форм и сохранение результатов

Раздел: Разработка на PHP -> Обработка форм

Основы создания опроса на PHP

Как создать опрос с сохранением ответов в базе данных MySQL?

Наиболее эффективное решение предполагает использование реляционной базы данных. Это обеспечивает структурированное хранение, быстрый поиск и возможность построения статистики.

Шаг 1. Создание таблицы. Пример SQL-запроса для таблицы ответов:


CREATE TABLE survey_responses (
    id INT AUTO_INCREMENT PRIMARY KEY,
    question_id INT NOT NULL,
    answer VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
  

Шаг 2. Форма опроса. HTML-форма с вариантами ответов (радиокнопки).


<form action="submit.php" method="POST">
  <p>Какой язык программирования вы предпочитаете?</p>
  <label><input type="radio" name="answer" value="PHP"> PHP</label>
  <label><input type="radio" name="answer" value="Python"> Python</label>
  <label><input type="radio" name="answer" value="JavaScript"> JavaScript</label>
  <input type="hidden" name="question_id" value="1">
  <button type="submit">Отправить</button>
</form>
  

Шаг 3. Обработчик submit.php. Код принимает данные, проверяет их и сохраняет через подготовленный запрос.


<?php
$conn = new mysqli('localhost', 'user', 'password', 'survey_db');
if ($conn->connect_error) {
    die('Ошибка подключения: ' . $conn->connect_error);
}

$answer = $_POST['answer'] ?? '';
$question_id = (int)($_POST['question_id'] ?? 0);

if (empty($answer) || $question_id <= 0) {
    die('Некорректные данные');
}

$stmt = $conn->prepare('INSERT INTO survey_responses (question_id, answer) VALUES (?, ?)');
$stmt->bind_param('is', $question_id, $answer);
$stmt->execute();
$stmt->close();
$conn->close();

echo 'Спасибо, ваш ответ сохранён!';
?>
  

Типичные проблемы:

  • SQL-инъекции при конкатенации строк. Решение – использовать prepared statements.
  • Ошибки подключения к БД (неверные реквизиты, отсутствие базы). Проверять через connect_error.
  • Дублирование ответов от одного пользователя. Можно добавить сессионный контроль или проверку по IP.

Как организовать опрос без базы данных, используя файлы?

Если база данных недоступна или требуется простая реализация, ответы можно сохранять в текстовый файл (JSON, CSV).


<?php
$file = 'responses.json';
$data = json_decode(file_get_contents($file), true) ?? [];
$data[] = [
    'question_id' => 1,
    'answer' => $_POST['answer'],
    'timestamp' => date('Y-m-d H:i:s')
];
file_put_contents($file, json_encode($data, JSON_PRETTY_PRINT));
echo 'Ответ сохранён в файл.';
?>
  

Проблемы:

  • Блокировка файла при одновременных записях – использовать flock().
  • Большой файл может замедлить чтение/запись. Для больших объёмов подходит только БД.
  • Безопасность: файл не должен быть доступен извне (размещать выше DocumentRoot).

Как сохранить ответы только на время сессии, без постоянного хранения?

Этот вариант подходит для одноразовых опросов в рамках одной сессии браузера.


<?php
session_start();
if (!isset($_SESSION['survey_answers'])) {
    $_SESSION['survey_answers'] = [];
}
$_SESSION['survey_answers'][] = [
    'question_id' => $_POST['question_id'],
    'answer' => $_POST['answer']
];
echo 'Ответ сохранён в сессии.';
?>
  

Недостатки:

  • Данные теряются при закрытии браузера или истечении сессии.
  • Невозможно агрегировать результаты разных пользователей.

Как отправить ответ опроса без перезагрузки страницы, используя AJAX?

AJAX позволяет асинхронно отправлять данные на сервер. Пример на JavaScript (fetch) и PHP.

Клиентская часть:


document.getElementById('survey-form').addEventListener('submit', async function(e) {
    e.preventDefault();
    const formData = new FormData(this);
    const response = await fetch('submit_ajax.php', { method: 'POST', body: formData });
    const result = await response.text();
    document.getElementById('message').innerText = result;
});
  

Серверная часть (submit_ajax.php):


<?php
// Валидация и сохранение (например, в БД)
echo 'Ответ получен асинхронно.';
?>
  

Возможные трудности:

  • Ошибки CORS, если запрос идёт на другой домен. Настраивать заголовки.
  • Необходимость отправлять CSRF-токен для защиты от подделки.
  • Обработка ошибок на клиенте (catch).

Как быстро создать опрос в крупном проекте с использованием фреймворка (Laravel, Symfony)?

Фреймворки предоставляют встроенные средства для работы с формами, валидацией и ORM. Например, в Laravel можно создать модель и миграцию, а затем использовать фасад Validator. Это ускоряет разработку, но требует знания фреймворка.


// Пример в Laravel (контроллер)
public function store(Request $request) {
    $validated = $request->validate([
        'question_id' => 'required|integer',
        'answer' => 'required|string|max:255'
    ]);
    SurveyResponse::create($validated);
    return 'Ответ сохранён';
}
  

Усложнения:

  • Потребуется установка и настройка фреймворка.
  • Для небольших проектов может быть избыточно.

Расширенные примеры реализации опроса

Пример 1. Полный цикл: форма, обработка, отображение статистики (MySQL)

Покажем законченный пример с созданием таблицы, формой, обработчиком и страницей результатов.

1. SQL для создания таблицы и вставки вопроса:

Пример

CREATE TABLE survey_responses (
    id INT AUTO_INCREMENT PRIMARY KEY,
    question_id INT NOT NULL,
    answer VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

INSERT INTO questions (id, title) VALUES (1, 'Ваш любимый язык программирования?');

2. Файл form.php (HTML + PHP для отображения формы):

Пример

<?php
$conn = new mysqli('localhost', 'root', '', 'survey');
$question = $conn->query("SELECT * FROM questions WHERE id=1")->fetch_assoc();
?>
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Опрос</title></head>
<body>
<h2><?= $question['title'] ?></h2>
<form action="submit.php" method="POST">
  <input type="hidden" name="question_id" value="1">
  <label><input type="radio" name="answer" value="PHP"> PHP</label><br>
  <label><input type="radio" name="answer" value="Python"> Python</label><br>
  <label><input type="radio" name="answer" value="JavaScript"> JavaScript</label><br>
  <button type="submit">Голосовать</button>
</form>
</body>
</html>

3. Файл submit.php (обработка с prepared statement):

Пример

<?php
$conn = new mysqli('localhost', 'root', '', 'survey');
if ($conn->connect_error) {
    die('Ошибка подключения: ' . $conn->connect_error);
}

$question_id = (int)$_POST['question_id'];
$answer = $_POST['answer'] ?? '';
$allowed = ['PHP', 'Python', 'JavaScript'];

if (!in_array($answer, $allowed)) {
    die('Недопустимый ответ');
}

$stmt = $conn->prepare('INSERT INTO survey_responses (question_id, answer) VALUES (?, ?)');
$stmt->bind_param('is', $question_id, $answer);
$stmt->execute();
$stmt->close();
$conn->close();
header('Location: results.php');
?>

4. Файл results.php (отображение статистики):

Пример

<?php
$conn = new mysqli('localhost', 'root', '', 'survey');
$result = $conn->query("SELECT answer, COUNT(*) as cnt FROM survey_responses WHERE question_id=1 GROUP BY answer ORDER BY cnt DESC");
?>
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Результаты опроса</title></head>
<body>
<h2>Результаты</h2>
<ul>
<?php while ($row = $result->fetch_assoc()): ?>
  <li><?= $row['answer'] ?>: <?= $row['cnt'] ?> голосов</li>
<?php endwhile; ?>
</ul>
</body>
</html>

Результат вывода (пример):

PHP: 15 голосов
Python: 10 голосов
JavaScript: 8 голосов

Пример 2. Асинхронная отправка с использованием fetch и JSON

Этот пример показывает опрос, который отправляет данные через AJAX и получает JSON-ответ.

Клиентский код (form_ajax.html):

Пример

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Асинхронный опрос</title>
<script>
document.addEventListener('DOMContentLoaded', function() {
    const form = document.getElementById('survey-ajax');
    form.addEventListener('submit', async function(e) {
        e.preventDefault();
        const formData = new FormData(form);
        try {
            const response = await fetch('process_ajax.php', { method: 'POST', body: formData });
            const result = await response.json();
            document.getElementById('result').innerText = result.message;
        } catch (error) {
            document.getElementById('result').innerText = 'Ошибка: ' + error;
        }
    });
});
</script>
</head>
<body>
<h2>Ваш любимый цвет?</h2>
<form id="survey-ajax">
  <label><input type="radio" name="answer" value="Красный"> Красный</label>
  <label><input type="radio" name="answer" value="Синий"> Синий</label>
  <label><input type="radio" name="answer" value="Зелёный"> Зелёный</label>
  <input type="hidden" name="question_id" value="2">
  <button type="submit">Отправить</button>
</form>
<div id="result"></div>
</body>
</html>

Серверный код (process_ajax.php):

Пример

<?php
header('Content-Type: application/json');

$answer = $_POST['answer'] ?? '';
$question_id = (int)($_POST['question_id'] ?? 0);

if (empty($answer) || $question_id <= 0) {
    echo json_encode(['message' => 'Некорректные данные']);
    exit;
}

// Здесь можно подключиться к БД и сохранить ответ
// Для примера просто возвращаем сообщение
echo json_encode(['message' => "Спасибо! Ваш ответ: $answer"]);
?>

Результат при успешной отправке (JSON):

{"message":"Спасибо! Ваш ответ: Синий"}

Пример 3. Хранение в CSV-файле с блокировкой

Для небольших опросов без БД удобно использовать CSV. Код с защитой от одновременной записи.

Пример

<?php
$file = 'responses.csv';
$newLine = [$_POST['question_id'], $_POST['answer'], date('Y-m-d H:i:s')];

$handle = fopen($file, 'a');
if (flock($handle, LOCK_EX)) {
    fputcsv($handle, $newLine);
    flock($handle, LOCK_UN);
} else {
    echo 'Не удалось заблокировать файл';
}
fclose($handle);
echo 'Ответ добавлен в CSV';
?>

Содержимое CSV после нескольких записей:

1,PHP,2025-04-10 12:00:00
1,Python,2025-04-10 12:05:00
2,Красный,2025-04-10 12:10:00
- Index php form (обработка html-форм на php)
- Php page post (post-запрос на страницу php)
- Survey php (создание опроса на php)
- Php input value (значение поля ввода php)

Создание опроса на PHP - comments

En
Survey php (php)