Экзамен по PHP: руководство по созданию index.php

Раздел: Обучение -> Подготовка к экзаменам по PHP

Экзаменационная страница на PHP: основные подходы

Как создать простой экзаменационный тест на одной странице index.php?

Основной подход заключается в размещении всех вопросов и механизма проверки в одном файле index.php. Вопросы хранятся в массиве PHP, форма отправляется методом POST, а результат выводится после обработки. Такой вариант подходит для небольших тестов с фиксированным набором вопросов, не требующих сохранения прогресса между сессиями.


<?php
// Вопросы: массив, где каждый элемент содержит текст вопроса, варианты ответов и правильный индекс
$questions = [
    [
        'text' => 'Какая функция используется для вывода текста в PHP?',
        'options' => ['echo', 'print', 'write', 'output'],
        'correct' => 0
    ],
    [
        'text' => 'Какой символ используется для обозначения переменной в PHP?',
        'options' => ['$', '@', '#', '&'],
        'correct' => 0
    ]
];

$score = 0;
$showResult = false;

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $showResult = true;
    foreach ($questions as $index => $q) {
        $selected = $_POST['q' . $index] ?? null;
        if ($selected !== null && (int)$selected === $q['correct']) {
            $score++;
        }
    }
}
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Экзамен по PHP</title>
</head>
<body>
<h2>Тест по основам PHP</h2>
<form method="post">
    <?php foreach ($questions as $i => $q): ?>
    <fieldset>
        <legend><?= htmlspecialchars($q['text']) ?></legend>
        <?php foreach ($q['options'] as $j => $opt): ?>
        <label><input type="radio" name="q<?= $i ?>" value="<?= $j ?>"><?= htmlspecialchars($opt) ?></label><br>
        <?php endforeach; ?>
    </fieldset>
    <?php endforeach; ?>
    <button type="submit">Проверить ответы</button>
</form>

<?php if ($showResult): ?>
<div>
    <p class="fw-bold">Результат: <?= $score ?> из <?= count($questions) ?></p>
</div>
<?php endif; ?>
</body>
</html>
  

Index php exam (экзамен по php (index.php))

В этом примере все вопросы обрабатываются сразу после отправки формы. Результат показывается на той же странице. Важно экранировать вывод с помощью htmlspecialchars для защиты от XSS.

Как организовать тест с переходом между страницами через сессии?

Если тест состоит из нескольких страниц (по одному вопросу на страницу), удобно использовать сессии для хранения текущего состояния. Скрипт index.php может служить точкой входа, а последующие страницы обрабатывать по номеру вопроса из сессии.


<?php
session_start();

$questions = [...]; // тот же массив

// Инициализация прогресса
if (!isset($_SESSION['step'])) {
    $_SESSION['step'] = 0;
    $_SESSION['answers'] = [];
}

// Если форма отправлена, сохраняем ответ и увеличиваем шаг
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $selected = $_POST['answer'] ?? null;
    $_SESSION['answers'][$_SESSION['step']] = $selected;
    $_SESSION['step']++;
}

$current = $_SESSION['step'];
if ($current >= count($questions)) {
    // Подсчет результатов
    $score = 0;
    foreach ($questions as $i => $q) {
        if (isset($_SESSION['answers'][$i]) && (int)$_SESSION['answers'][$i] === $q['correct']) {
            $score++;
        }
    }
    session_destroy();
    echo "Результат: $score из " . count($questions);
    exit;
}

$q = $questions[$current];
?>
<form method="post">
    <p><?= htmlspecialchars($q['text']) ?></p>
    <?php foreach ($q['options'] as $j => $opt): ?>
    <label><input type="radio" name="answer" value="<?= $j ?>" required><?= htmlspecialchars($opt) ?></label><br>
    <?php endforeach; ?>
    <button type="submit">Далее</button>
</form>
  

Важно:

перед использованием сессий необходимо вызвать session_start() в начале скрипта. Ошибка: забыть стартовать сессию или не завершить её при подсчете результатов.

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

Для динамического теста с большим количеством вопросов используется база данных. Пример с PDO:


<?php
$dsn = 'mysql:host=localhost;dbname=exam;charset=utf8';
$pdo = new PDO($dsn, 'user', 'pass');

$stmt = $pdo->query('SELECT id, question, options, correct FROM questions LIMIT 5');
$questions = $stmt->fetchAll(PDO::FETCH_ASSOC);

// Поле options хранится как JSON строка, декодируем
foreach ($questions as &$q) {
    $q['options'] = json_decode($q['options'], true);
}
unset($q);

// Далее логика аналогична первому варианту
?>
  

Такая структура позволяет легко добавлять, редактировать и выбирать вопросы. Возможная проблема: неправильная кодировка соединения – следует указывать charset в DSN.

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

Для улучшения пользовательского опыта можно отправлять ответы через AJAX. Основной файл index.php будет содержать форму и JavaScript, а обработка – отдельный скрипт (например, check.php). Однако в рамках одной страницы можно совместить.


// index.php
<script>
document.querySelector('form').addEventListener('submit', function(e) {
    e.preventDefault();
    let formData = new FormData(this);
    fetch('check.php', {
        method: 'POST',
        body: formData
    })
    .then(response => response.json())
    .then(data => {
        document.getElementById('result').innerText = data.result;
    });
});
</script>
  

На стороне сервера check.php возвращает JSON с результатом. Это позволяет не перезагружать страницу.

Какие типичные ошибки возникают при создании экзаменационного index.php и как их избежать?

  • Не экранированный вывод – приводит к XSS-уязвимости. Решение: всегда использовать htmlspecialchars().
  • Отсутствие проверки на существование POST-параметра – вызывает ошибку уровня Notice. Решение: проверять с помощью isset() или использовать оператор ??.
  • Потеря прогресса при использовании сессий – сессия может быть не стартована или уничтожена раньше времени. Решение: строго соблюдать порядок session_start() перед любым выводом.
  • Проблемы с кодировкой – русские символы отображаются как вопросики. Решение: установить header('Content-Type: text/html; charset=utf-8'); и убедиться, что файл сохранен в UTF-8 без BOM.
  • Неправильное сравнение типов – при проверке ответа строка '0' может не совпасть с числом 0. Решение: использовать строгое сравнение === или приводить типы.

Дополнительные примеры и расширенные сценарии

Пример с PDO и случайной выборкой вопросов

Предположим, что таблица questions содержит поля id, question, options (JSON), correct (индекс верного варианта). Ниже приведен код, который выбирает 10 случайных вопросов и выводит тест.

Пример

<?php
$dsn = 'mysql:host=localhost;dbname=php_exam;charset=utf8mb4';
$user = 'root';
$pass = '';

try {
    $pdo = new PDO($dsn, $user, $pass, [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    ]);
} catch (PDOException $e) {
    die('Ошибка подключения к БД: ' . $e->getMessage());
}

// Получаем 10 случайных вопросов
$stmt = $pdo->query('SELECT id, question, options, correct FROM questions ORDER BY RAND() LIMIT 10');
$questions = $stmt->fetchAll();

// Декодируем JSON-опции
foreach ($questions as &$q) {
    $q['options'] = json_decode($q['options'], true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        // Если JSON некорректен, можно задать запасные варианты
        $q['options'] = ['Ошибка данных'];
    }
}
unset($q);

// Далее форма и обработка
?>
Вывод: массив $questions содержит 10 случайных записей. Каждый элемент имеет ключи: id, question, options (массив), correct.

Пример с несколькими типами вопросов (одиночный выбор, множественный, текстовый)

Расширим массив вопросов, добавив поле type: 'single', 'multiple', 'text'. Для каждого типа – своя логика проверки.

Пример

<?php
$questions = [
    [
        'type' => 'single',
        'text' => 'Какая функция выводит отформатированный массив?',
        'options' => ['print_r', 'var_dump', 'echo', 'array_print'],
        'correct' => 0
    ],
    [
        'type' => 'multiple',
        'text' => 'Какие из перечисленных являются суперглобальными массивами? (выберите все подходящие)',
        'options' => ['$_GET', '$_POST', '$_SESSION', '$_COOKIE'],
        'correct' => [0, 1] // индексы верных вариантов
    ],
    [
        'type' => 'text',
        'text' => 'Напишите имя функции для установки cookie в PHP:',
        'correct' => 'setcookie' // регистронезависимо
    ]
];

// Пример обработки для множественного выбора
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    foreach ($questions as $i => $q) {
        if ($q['type'] === 'multiple') {
            $selected = $_POST['q' . $i] ?? [];
            // $selected - массив выбранных значений
            $correct = $q['correct'];
            sort($selected);
            sort($correct);
            if ($selected === $correct) {
                // верно
            }
        }
    }
}
?>

<!-- Форма для множественного выбора -->
<fieldset>
    <legend><?= htmlspecialchars($q['text']) ?></legend>
    <?php foreach ($q['options'] as $j => $opt): ?>
    <label><input type="checkbox" name="q<?= $i ?>[]" value="<?= $j ?>"><?= htmlspecialchars($opt) ?></label><br>
    <?php endforeach; ?>
</fieldset>
Результат: для множественного выбора проверяется совпадение массивов после сортировки. Для текстового ответа – сравнение строк без учета регистра (strcasecmp).
Пример с ограничением времени выполнения

Добавим таймер с помощью JavaScript и проверку времени на сервере через сессию.

Пример

// Начало теста: сохраняем время начала в сессию
$_SESSION['start_time'] = time();
$duration = 600; // 10 минут в секундах

// При проверке ответов
if (time() - $_SESSION['start_time'] > $duration) {
    die('Время истекло');
}
Если пользователь превысил лимит, скрипт завершается с сообщением. На клиенте можно показывать обратный отсчет.

Пример с использованием файла JSON для хранения вопросов

Для небольших тестов удобно хранить вопросы в файле questions.json, а не в БД.

Пример

// questions.json
[
    {
        "text": "Какая функция создает массив?",
        "options": ["array()", "create_array()", "make_array()"],
        "correct": 0
    }
]

// index.php
$json = file_get_contents('questions.json');
$questions = json_decode($json, true);
if ($questions === null) {
    die('Ошибка чтения файла вопросов');
}
// далее аналогично первому примеру
Файл questions.json легко редактировать в любом текстовом редакторе. Важно: проверять корректность JSON с помощью json_last_error().

Экзамен по PHP (index.php) - comments

En
Index php exam (php)