Примеры заданий по PHP с пояснениями
Основные подходы к решению заданий PHP
Как вычислить сумму целых чисел от 1 до N?
Самое эффективное решение для суммы натуральных чисел - использование математической формулы N*(N+1)/2. Этот способ выполняется за константное время и не требует циклов.
<?php
$n = 100;
$sum = $n * ($n + 1) / 2;
echo "Сумма от 1 до $n = $sum";
?>
задания php (задания по php)
Сумма от 1 до 100 = 5050
Типичная ошибка: переполнение типа данных при больших N (например, N > 1e9). Для таких случаев следует использовать float или библиотеку для работы с большими числами (bcmath). Также возможно случайное деление на целое число, если N нечётное - результат будет верным, так как одно из чисел чётное.
Как посчитать сумму с помощью цикла for?
Если требуется продемонстрировать работу цикла (например, в учебных целях), можно использовать for.
<?php
$n = 100;
$sum = 0;
for ($i = 1; $i <= $n; $i++) {
$sum += $i;
}
echo "Сумма = $sum";
?>
Сумма = 5050
Проблема: при больших N (100 млн) время выполнения становится заметным. Также легко допустить ошибку в условии цикла - пропустить знак равенства ($i < $n) или неверную инициализацию.
Как сделать рекурсивное вычисление суммы?
Рекурсия полезна для понимания стека вызовов, но неэффективна для больших N из-за лимита рекурсии.
<?php
function sumRecursive($n) {
if ($n <= 1) {
return $n;
}
return $n + sumRecursive($n - 1);
}
$result = sumRecursive(100);
echo "Рекурсивная сумма = $result";
?>
Рекурсивная сумма = 5050
Ошибки: превышение лимита рекурсии (PHP Fatal error: Maximum function nesting level) при N > 1000. Для учебных целей можно увеличить лимит функцией ini_set('xdebug.max_nesting_level', 10000), но это не рекомендуется на практике.
Как применить встроенную функцию array_sum?
Если нужно просуммировать элементы массива, можно использовать array_sum. Этот способ подходит, когда числа уже находятся в массиве.
<?php
$numbers = range(1, 100);
$sum = array_sum($numbers);
echo "Сумма = $sum";
?>
Сумма = 5050
Варианты использования: обработка данных, полученных из базы данных или файла.
Как вывести таблицу умножения 10x10?
Основной способ - вложенные циклы for. Внутренний цикл проходит по столбцам, внешний - по строкам. Результат оформляется в виде HTML-таблицы.
<?php
echo '<table border="1">';
for ($i = 1; $i <= 10; $i++) {
echo '<tr>';
for ($j = 1; $j <= 10; $j++) {
echo '<td>' . ($i * $j) . '</td>';
}
echo '</tr>';
}
echo '</table>';
?>
Результат - таблица с ячейками от 1 до 100.
Ошибка: забыть конкатенацию или неправильно закрыть теги. Также возможен вывод без HTML-разметки, что даст нечитаемый поток чисел.
Как сделать таблицу умножения с использованием while?
<?php
$i = 1;
echo '<table border="1">';
while ($i <= 10) {
echo '<tr>';
$j = 1;
while ($j <= 10) {
echo '<td>' . ($i * $j) . '</td>';
$j++;
}
echo '</tr>';
$i++;
}
echo '</table>';
?>
Циклы while удобны, когда количество итераций заранее не известно, но здесь оно фиксировано.
Распространённая проблема: забыть увеличить счётчик ($i++) - возникнет бесконечный цикл.
Как сгенерировать таблицу через двумерный массив?
Такой подход удобен, если данные нужно обработать до вывода (например, выделить чётные числа).
<?php
$table = [];
for ($i = 1; $i <= 10; $i++) {
for ($j = 1; $j <= 10; $j++) {
$table[$i][$j] = $i * $j;
}
}
// Вывод
echo '<table border="1">';
foreach ($table as $row) {
echo '<tr>';
foreach ($row as $cell) {
echo '<td>' . $cell . '</td>';
}
echo '</tr>';
}
echo '</table>';
?>
Можно модифицировать значения перед выводом.
Как проверить, является ли строка палиндромом?
Базовое решение - сравнить строку с её перевёрнутой версией, используя strrev.
<?php
$str = 'radar';
$reversed = strrev($str);
if ($str === $reversed) {
echo "Это палиндром";
} else {
echo "Не палиндром";
}
?>
Это палиндром
Нюансы: функция strrev не обрабатывает многобайтовые кодировки (UTF-8). Для кириллицы нужно использовать mb_strrev или разбивать строку на массив символов. Также игнорирование регистра и пробелов - рекомендуется перед проверкой привести строку к нижнему регистру и удалить все небуквенные символы.
Как реализовать проверку палиндрома без strrev?
Поэлементное сравнение символов с обоих концов.
<?php
function isPalindrome($str) {
$len = strlen($str);
for ($i = 0; $i < $len / 2; $i++) {
if ($str[$i] !== $str[$len - $i - 1]) {
return false;
}
}
return true;
}
$test = 'level';
echo isPalindrome($test) ? 'Да' : 'Нет';
?>
Да
Преимущество - контроль над условиями сравнения.
Ошибка: при использовании многобайтовых строк $str[$i] получит некорректные байты. Решение - работать с mb_substr или предварительно преобразовать в массив символов через preg_split.
Как игнорировать пробелы и знаки препинания?
<?php
$phrase = 'А роза упала на лапу Азора';
$clean = preg_replace('/[^\p{L}]/u', '', mb_strtolower($phrase));
$reversed = implode('', array_reverse(preg_split('//u', $clean, -1, PREG_SPLIT_NO_EMPTY)));
if ($clean === $reversed) {
echo "Фраза - палиндром";
} else {
echo "Нет";
}
?>
Фраза - палиндром
Здесь используется регулярное выражение для удаления всего, кроме букв, и корректная работа с Unicode.
Как создать простой калькулятор на PHP (обработка формы)?
Стандартное задание: принимаем два числа и оператор через POST или GET, вычисляем результат, выводим. Основное решение - с использованием условных операторов.
<!DOCTYPE html>
<form method="post">
Число 1: <input type="number" name="a">
Оператор: <select name="op">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
Число 2: <input type="number" name="b">
<input type="submit">
</form>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$a = $_POST['a'] ?? 0;
$b = $_POST['b'] ?? 0;
$op = $_POST['op'] ?? '+';
switch ($op) {
case '+': $result = $a + $b; break;
case '-': $result = $a - $b; break;
case '*': $result = $a * $b; break;
case '/':
if ($b == 0) {
$result = 'Деление на ноль';
} else {
$result = $a / $b;
}
break;
default: $result = 'Неизвестная операция';
}
echo "Результат: $result";
}
?>
Ошибки: отсутствие проверки на существование входных данных (при первом открытии страницы), уязвимость XSS при выводе без экранирования, использование == вместо === при сравнении с нулём. Рекомендуется применять htmlspecialchars для вывода и filter_input для получения данных.
Как реализовать калькулятор с помощью функции eval?
Не рекомендуется из соображений безопасности, но для учебных целей можно показать:
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$expression = $_POST['a'] . ' ' . $_POST['op'] . ' ' . $_POST['b'];
eval('$result = ' . $expression . ';');
echo $result;
}
?>
Проблемы: выполнение произвольного кода (если пользователь передаст 1; system('rm -rf /');//). Использовать только в закрытом окружении.
Как обработать форму с валидацией и сохранением данных?
<?php
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$a = filter_input(INPUT_POST, 'a', FILTER_VALIDATE_FLOAT);
$b = filter_input(INPUT_POST, 'b', FILTER_VALIDATE_FLOAT);
$op = $_POST['op'] ?? '';
if ($a === false || $b === false) {
$errors[] = 'Введите корректные числа';
}
if (!in_array($op, ['+', '-', '*', '/'])) {
$errors[] = 'Неверный оператор';
}
if (empty($errors) && $op === '/' && $b == 0) {
$errors[] = 'Деление на ноль';
}
if (empty($errors)) {
$result = match($op) {
'+' => $a + $b,
'-' => $a - $b,
'*' => $a * $b,
'/' => $a / $b,
};
}
}
?>
<form method="post">
<input type="text" name="a" value="<?= htmlspecialchars($_POST['a'] ?? '') ?>">
<select name="op">...</select>
<input type="text" name="b" value="<?= htmlspecialchars($_POST['b'] ?? '') ?>">
<input type="submit">
</form>
<?php if (!empty($errors)): ?>
<ul><?php foreach ($errors as $e): ?><li><?= htmlspecialchars($e) ?></li><?php endforeach; ?></ul>
<?php elseif (isset($result)): ?>
<p>Результат: <?= htmlspecialchars($result) ?></p>
<?php endif; ?>
Данный вариант показывает полную обработку ошибок и сохранение введённых значений.
Дополнительные расширенные примеры
В этом разделе представлены более сложные и редко встречающиеся в базовых учебных заданиях решения, которые помогут углубить понимание PHP.
Рекурсивный обход директорий с фильтрацией по расширению
Задание: вывести все файлы с расширением .php из заданной папки и её подпапок.
<?php
function scanPHPFiles($dir) {
$files = [];
$items = scandir($dir);
foreach ($items as $item) {
if ($item == '.' || $item == '..') continue;
$path = $dir . DIRECTORY_SEPARATOR . $item;
if (is_dir($path)) {
$files = array_merge($files, scanPHPFiles($path));
} elseif (pathinfo($path, PATHINFO_EXTENSION) === 'php') {
$files[] = $path;
}
}
return $files;
}
$targetDir = '/path/to/project';
$phpFiles = scanPHPFiles($targetDir);
print_r($phpFiles);
?>
Array
(
[0] => /path/to/project/index.php
[1] => /path/to/project/lib/functions.php
...
)
Проблема: при очень глубокой вложенности может превыситься лимит рекурсии. Альтернатива - итератор RecursiveDirectoryIterator.
<?php
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($targetDir, RecursiveDirectoryIterator::SKIP_DOTS)
);
$phpFiles = [];
foreach ($iterator as $file) {
if ($file->getExtension() === 'php') {
$phpFiles[] = $file->getPathname();
}
}
print_r($phpFiles);
?>
Использование встроенных итераторов упрощает код и снижает риск ошибок.
Работа с JSON: чтение, изменение и запись в файл
Допустим, есть файл data.json с массивом пользователей. Требуется добавить нового пользователя и сохранить.
<?php
// Чтение
$json = file_get_contents('data.json');
$users = json_decode($json, true);
if (json_last_error() !== JSON_ERROR_NONE) {
die('Ошибка декодирования JSON: ' . json_last_error_msg());
}
// Добавление
$users[] = [
'id' => count($users) + 1,
'name' => 'Новый пользователь',
'email' => 'new@example.com'
];
// Запись
$newJson = json_encode($users, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
if (file_put_contents('data.json', $newJson) === false) {
die('Ошибка записи файла');
}
echo 'Данные сохранены';
?>
Типичные ошибки: не проверяется возвращаемое значение file_get_contents (может быть false), не обрабатывается исключение при записи в защищённую директорию, отсутствие проверки прав доступа. Также стоит использовать JSON_THROW_ON_ERROR в PHP 7.3+ для генерации исключений.
Как работать с JSON через потоки (streams)?
<?php
$stream = fopen('data.json', 'r+');
if (flock($stream, LOCK_EX)) {
$content = stream_get_contents($stream);
$data = json_decode($content, true);
$data[] = ['new' => 'record'];
ftruncate($stream, 0);
rewind($stream);
fwrite($stream, json_encode($data, JSON_PRETTY_PRINT));
fflush($stream);
flock($stream, LOCK_UN);
}
fclose($stream);
?>
Блокировка предотвращает одновременную запись из нескольких процессов.
Генерация и проверка CSRF-токенов (учебная задача по безопасности)
Создание формы с защитой от подделки межсайтовых запросов.
<?php
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
$token = $_SESSION['csrf_token'];
?>
<form method="post" action="process.php">
<input type="hidden" name="csrf_token" value="<?= $token ?>">
<input type="text" name="data">
<input type="submit">
</form>
<!-- process.php -->
<?php
session_start();
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die('CSRF атака обнаружена');
}
// Обработка данных
?>
Регулярная ротация токенов (после каждой отправки) повышает безопасность.
Кэширование результатов сложных вычислений в файле
Допустим, нужно вычислить последовательность Фибоначчи до N и сохранить в файл, чтобы не повторять расчёт.
<?php
$cacheFile = 'fib_cache_' . $n . '.txt';
if (file_exists($cacheFile)) {
$result = unserialize(file_get_contents($cacheFile));
} else {
$result = [0, 1];
for ($i = 2; $i < $n; $i++) {
$result[] = $result[$i-1] + $result[$i-2];
}
file_put_contents($cacheFile, serialize($result));
}
print_r($result);
?>
Недостаток: сериализованные данные могут быть изменены пользователем. Вместо этого можно использовать json_encode или специализированные системы кэширования (Memcached, Redis).
Работа с PDO: подготовленные запросы и транзакции
Пример вставки нескольких записей в базу данных с использованием транзакции.
<?php
$dsn = 'mysql:host=localhost;dbname=test;charset=utf8';
$user = 'root';
$pass = '';
try {
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);
$pdo->beginTransaction();
$stmt = $pdo->prepare('INSERT INTO users (name, email) VALUES (:name, :email)');
$users = [
['name' => 'Alice', 'email' => 'alice@example.com'],
['name' => 'Bob', 'email' => 'bob@example.com']
];
foreach ($users as $user) {
$stmt->execute($user);
}
$pdo->commit();
echo 'Записи добавлены';
} catch (PDOException $e) {
$pdo->rollBack();
echo 'Ошибка: ' . $e->getMessage();
}
?>
Транзакции гарантируют, что в случае ошибки не останутся частично вставленные данные.
Собственная реализация функции array_map для обучения
Чтобы понять, как работают встроенные функции, можно написать аналог.
<?php
function myArrayMap(callable $callback, array $array): array {
$result = [];
foreach ($array as $key => $value) {
$result[$key] = $callback($value, $key);
}
return $result;
}
$numbers = [1, 2, 3];
$squared = myArrayMap(function($n) { return $n * $n; }, $numbers);
print_r($squared);
?>
Array
(
[0] => 1
[1] => 4
[2] => 9
)
Данный пример демонстрирует работу с callback-функциями и сохраняет ключи.