Примеры заданий по PHP с пояснениями

Раздел: Обучение 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-функциями и сохраняет ключи.

Задания по PHP - comments

En
задания php (php)