PHP викторины: от простого скрипта до полноценного тестирующего модуля

Раздел: Веб-разработка на PHP -> PHP викторины и тесты

Разработка викторины на PHP: ключевые подходы и примеры

PHP викторины (quizzes) представляют собой интерактивные опросники, которые позволяют проверять знания пользователей. В этом материале рассматриваются различные способы реализации таких опросников: от простых скриптов на чистом PHP до более сложных решений с использованием баз данных и объектно-ориентированного программирования.

Как создать базовую викторину с проверкой ответов и подсчетом баллов?

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


<?php
session_start();
// Массив вопросов: id, текст, варианты, правильный ответ
$questions = [
   1 => [
      'text' => 'Какой оператор используется для объявления переменной в PHP?',
      'options' => ['var', 'let', '$', 'dim'],
      'answer' => 2 // индекс правильного ответа (0-3)
   ],
   2 => [
      'text' => 'Какая функция выводит массив в читаемом виде?',
      'options' => ['print_r', 'echo', 'var_dump', 'array_print'],
      'answer' => 0
   ]
];

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $_SESSION['answers'][$_POST['qid']] = $_POST['option'];
}
if (!isset($_SESSION['current'])) {
    $_SESSION['current'] = 1;
}

$qid = $_SESSION['current'];
$question = $questions[$qid] ?? null;
if (!$question) {
    // Подсчет результата
    $score = 0;
    foreach ($questions as $id => $q) {
        if (isset($_SESSION['answers'][$id]) && $_SESSION['answers'][$id] == $q['answer']) {
            $score++;
        }
    }
    echo "<p class=\"fw-bold\">Ваш результат: $score из " . count($questions) . "</p>";
    session_destroy();
    exit;
}
?>
<form method="post">
    <h4><?= $question['text'] ?></h4>
    <?php foreach ($question['options'] as $i => $opt): ?>
        <label><input type="radio" name="option" value="<?= $i ?>"> <?= $opt ?></label><br>
    <?php endforeach; ?>
    <input type="hidden" name="qid" value="<?= $qid ?>">
    <button type="submit">Ответить</button>
</form>

Возможные проблемы:

  • При перезагрузке страницы ответ может отправляться повторно. Решение: после обработки POST перенаправлять (header('Location: ...')).
  • Сессия может истечь до завершения викторины. Рекомендуется увеличить время жизни сессии или сохранять прогресс в базе данных.
  • Необходимо экранировать вывод для защиты от XSS. Используйте htmlspecialchars.

Цель использования:

Быстрая интеграция тестирования на небольшом сайте без внешних зависимостей. Подходит для простых опросов с фиксированным набором вопросов.

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

Вопросы извлекаются через PDO, что упрощает добавление новых тем и масштабирование.


// Подключение
$pdo = new PDO('mysql:host=localhost;dbname=quiz', 'root', '');
$stmt = $pdo->query('SELECT * FROM questions ORDER BY RAND() LIMIT 10');
$questions = $stmt->fetchAll(PDO::FETCH_ASSOC);

Чтобы избежать SQL-инъекций, используйте подготовленные запросы. При большом количестве вопросов убедитесь, что столбец с вариантами ответов структурирован (например, JSON).

Как реализовать загрузку вопросов из JSON-файла?

JSON удобен для переносимости данных.


$json = file_get_contents('questions.json');
$questions = json_decode($json, true);
if (json_last_error() !== JSON_ERROR_NONE) {
    die('Ошибка разбора JSON: ' . json_last_error_msg());
}

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

Как сделать викторину с асинхронной загрузкой вопросов (AJAX)?

Клиентский JavaScript отправляет запрос к PHP-скрипту, который возвращает вопрос в формате JSON.


// PHP-скрипт get_question.php
header('Content-Type: application/json');
$id = $_GET['id'] ?? 1;
$question = getQuestionFromDatabase($id);
echo json_encode($question);

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

Как применить объектно-ориентированный подход для создания викторины?

Классы Question, Quiz, Answer позволяют инкапсулировать логику и легко расширять функционал.


class Question {
    private $text;
    private $options;
    private $correctAnswer;

    public function __construct($text, $options, $correct) {
        $this->text = $text;
        $this->options = $options;
        $this->correctAnswer = $correct;
    }

    public function isCorrect($answer) {
        return $answer == $this->correctAnswer;
    }
    // геттеры...
}

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

Расширенные примеры создания PHP викторины

Викторина с таймером обратного отсчета

Реализация таймера требует синхронизации времени на сервере и клиенте. Используйте JavaScript для отображения и PHP для проверки.

Пример

// PHP: при старте викторины сохраняем время начала
$_SESSION['start_time'] = time();
$time_limit = 120; // секунд
// При отправке ответа проверяем, не истекло ли время
if (time() - $_SESSION['start_time'] > $time_limit) {
    // завершить викторину
}
Результат: пользователь может отвечать только в течение заданного интервала. По истечении времени викторина автоматически завершается.

Перемешивание вопросов и вариантов ответов

Используйте shuffle() для случайного порядка. Важно сохранять соответствие правильного ответа после перемешивания.

Пример

$question = ['text' => 'Столица Франции?', 'options' => ['Париж', 'Лондон', 'Берлин'], 'correct' => 0];
$correctValue = $question['options'][$question['correct']];
shuffle($question['options']);
$newCorrect = array_search($correctValue, $question['options']);
Результат: каждый пользователь видит вопросы и варианты в разном порядке, что уменьшает вероятность списывания.

Интеграция с внешним API (Open Trivia DB)

PHP может получать вопросы через cURL из открытого API.

Пример

$ch = curl_init('https://opentdb.com/api.php?amount=5&type=multiple');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$data = json_decode($response, true);
foreach ($data['results'] as $item) {
    echo $item['question'] . '<br>';
}
Результат: динамическая подборка вопросов из огромной базы. Требуется обработка HTML-сущностей в тексте вопроса.

Генерация отчета с результатами в виде диаграммы

После завершения викторины можно построить график распределения ответов. Используйте библиотеку Chart.js на фронтенде.

Пример

// PHP передает данные в JavaScript
$stats = [
    'correct' => $correctCount,
    'wrong' => $total - $correctCount
];
echo "<script>var data = " . json_encode($stats) . "</script>";
Результат: на странице отображается круговая диаграмма, показывающая процент правильных и неправильных ответов.

Создание REST API для управления викторинами

Используйте маршрутизацию на PHP (например, с помощью Slim Framework) для предоставления CRUD операций над вопросами.

Пример

// GET /questions - список вопросов
$app->get('/questions', function ($request, $response) {
    $questions = $db->query('SELECT * FROM questions')->fetchAll();
    return $response->withJson($questions);
});
Результат: мобильные приложения или внешние сервисы могут получать и отправлять данные викторины в стандартизированном формате.

PHP викторины - comments

En
Php quizzes (php)