Экзамен по PHP: руководство по созданию index.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().