PHP
Задачи на PHP с решениями: базовые упражнения
Эти упражнения ближе к реальной веб-практике PHP: вывести список товаров, отфильтровать массив, посчитать заказ, обработать форму, показать ошибки и сделать простую пагинацию. Все примеры без фреймворков, чтобы было видно сам язык и базовую логику
Создайте файл practice.php, запускайте его через встроенный сервер и проверяйте результат в браузере:
php -S localhost:8000
По этой теме полезно отдельно посмотреть Задачи по PHP для начинающих, чтобы расширить контекст и сравнить подходы
По этой теме полезно отдельно посмотреть Задачи по PHP для начинающих с решениями, чтобы расширить контекст и сравнить подходы
Что будем тренировать
- обычные и ассоциативные массивы
foreachи условия внутри цикла- функции для расчета
- безопасный вывод через
htmlspecialchars() - получение данных из
$_GETи$_POST - сбор ошибок формы в массив
- простую разбивку списка на страницы
Главный принцип: расчет и подготовку данных держим отдельно от HTML-вывода. Так код легче проверить, изменить и перенести в другой шаблон
Упражнение 1. Вывести карточки товаров
Условие: есть массив товаров. Нужно вывести название и цену каждого товара
Решение:
<?php
$products = [
['title' => 'Книга по PHP', 'price' => 900],
['title' => 'Видеокурс', 'price' => 3500],
['title' => 'Консультация', 'price' => 5000],
];
?>
<?php foreach ($products as $product): ?>
<div>
<h3><?= htmlspecialchars($product['title'], ENT_QUOTES, 'UTF-8') ?></h3>
<p><?= number_format($product['price'], 0, '.', ' ') ?> руб</p>
</div>
<?php endforeach; ?>
Что важно: HTML остается читаемым, а PHP только подставляет данные. Короткая запись <?= ... ?> выводит значение на страницу
Проверьте: добавьте товар с названием <b>Акция</b> и убедитесь, что тег не превратился в HTML
Упражнение 2. Показать только товары дешевле 3000
Условие: из массива товаров нужно вывести только доступные по цене товары
Решение:
<?php
$maxPrice = 3000;
foreach ($products as $product) {
if ($product['price'] <= $maxPrice) {
echo htmlspecialchars($product['title'], ENT_QUOTES, 'UTF-8') . '<br>';
}
}
Что важно: фильтр стоит внутри цикла. Каждый товар проверяется отдельно, и только подходящие товары попадают в вывод
Проверьте: поставьте $maxPrice = 1000, затем $maxPrice = 10000
Упражнение 3. Посчитать общую стоимость корзины
Условие: есть корзина с ценой и количеством. Нужно посчитать итоговую сумму
Решение:
<?php
$cart = [
['title' => 'Книга', 'price' => 900, 'count' => 2],
['title' => 'Курс', 'price' => 3500, 'count' => 1],
];
$total = 0;
foreach ($cart as $item) {
$total += $item['price'] * $item['count'];
}
echo 'Итого: ' . number_format($total, 0, '.', ' ') . ' руб';
Ожидаемый результат:
Итого: 5 300 руб
Что важно: итог считается не по цене товара, а по цене с учетом количества. Это типичная ошибка в первых задачах с корзиной
Проверьте: добавьте товар с количеством 0 и решите, нужно ли показывать его в корзине
Упражнение 4. Функция для цены со скидкой
Условие: написать функцию, которая возвращает цену после скидки и не занимается выводом HTML
Решение:
<?php
function priceWithDiscount(float $price, float $discountPercent): float
{
if ($discountPercent <= 0) {
return $price;
}
if ($discountPercent >= 100) {
return 0;
}
return $price - ($price * $discountPercent / 100);
}
echo priceWithDiscount(2000, 15);
Ожидаемый результат:
1700
Что важно: в функции есть защита для крайних случаев. Скидка 0 возвращает исходную цену, скидка 100 возвращает ноль
Упражнение 5. Форма обратной связи
Условие: форма принимает имя и сообщение. Нужно проверить, что оба поля заполнены
Решение:
<?php
$name = trim($_POST['name'] ?? '');
$message = trim($_POST['message'] ?? '');
$errors = [];
if ($name === '') {
$errors[] = 'Введите имя';
}
if ($message === '') {
$errors[] = 'Введите сообщение';
}
if ($errors) {
foreach ($errors as $error) {
echo '<p>' . htmlspecialchars($error, ENT_QUOTES, 'UTF-8') . '</p>';
}
} else {
echo 'Спасибо, ' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
}
Пример HTML-формы:
<form method="post">
<input name="name" placeholder="Имя">
<textarea name="message" placeholder="Сообщение"></textarea>
<button type="submit">Отправить</button>
</form>
Что важно: ошибки собираются в массив. Так пользователь увидит сразу все незаполненные поля, а не будет отправлять форму несколько раз
Проверьте: отправьте пустую форму, только имя, только сообщение и оба поля
Упражнение 6. Проверка email
Условие: нужно проверить email из формы и вывести понятную ошибку
Решение:
<?php
$email = trim($_POST['email'] ?? '');
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo 'Введите корректный email';
} else {
echo 'Email принят';
}
Что важно: не стоит проверять email вручную через одну проверку на @. В PHP есть встроенный фильтр, который для базовой проверки подходит лучше
Проверьте: mail@example.com, mail, mail@, пустую строку
Упражнение 7. Вывести таблицу заказов
Условие: есть список заказов. Нужно показать номер, имя клиента и сумму
Решение:
<?php
$orders = [
['id' => 101, 'client' => 'Анна', 'sum' => 2500],
['id' => 102, 'client' => 'Олег', 'sum' => 4300],
['id' => 103, 'client' => 'Мария', 'sum' => 900],
];
?>
<table>
<tr>
<th>Номер</th>
<th>Клиент</th>
<th>Сумма</th>
</tr>
<?php foreach ($orders as $order): ?>
<tr>
<td><?= (int) $order['id'] ?></td>
<td><?= htmlspecialchars($order['client'], ENT_QUOTES, 'UTF-8') ?></td>
<td><?= number_format($order['sum'], 0, '.', ' ') ?> руб</td>
</tr>
<?php endforeach; ?>
</table>
Что важно: числа можно приводить к int, а строки выводить через htmlspecialchars(). Так таблица остается безопаснее и предсказуемее
Проверьте: добавьте клиента с кавычками в имени
Упражнение 8. Группировка товаров по категории
Условие: есть товары с категориями. Нужно собрать товары по категориям
Решение:
<?php
$products = [
['title' => 'Книга', 'category' => 'books'],
['title' => 'Курс PHP', 'category' => 'courses'],
['title' => 'Курс SQL', 'category' => 'courses'],
];
$grouped = [];
foreach ($products as $product) {
$category = $product['category'];
$grouped[$category][] = $product['title'];
}
print_r($grouped);
Что важно: строка $grouped[$category][] = ... добавляет элемент внутрь группы. Если группы еще нет, PHP создаст ее автоматически как массив
Проверьте: добавьте новую категорию и товар без категории. Для товара без категории лучше заранее задать значение other
Упражнение 9. Простая пагинация
Условие: есть 25 элементов, на странице показываем по 10. Нужно получить элементы для текущей страницы
Решение:
<?php
$items = range(1, 25);
$perPage = 10;
$page = max(1, (int) ($_GET['page'] ?? 1));
$offset = ($page - 1) * $perPage;
$pageItems = array_slice($items, $offset, $perPage);
foreach ($pageItems as $item) {
echo "Элемент {$item}<br>";
}
Что важно: array_slice() берет часть массива. Для первой страницы смещение 0, для второй — 10, для третьей — 20
Проверьте: откройте страницу с параметрами ?page=1, ?page=2, ?page=3, ?page=0
Упражнение 10. Мини-каталог с поиском
Условие: пользователь вводит часть названия товара. Нужно вывести совпадения
Решение:
<?php
$query = mb_strtolower(trim($_GET['q'] ?? ''));
$products = ['Книга по PHP', 'Курс JavaScript', 'PHP консультация'];
foreach ($products as $product) {
$title = mb_strtolower($product);
if ($query === '' || mb_strpos($title, $query) !== false) {
echo htmlspecialchars($product, ENT_QUOTES, 'UTF-8') . '<br>';
}
}
Что важно: поиск приводится к нижнему регистру, чтобы запрос php находил и PHP. Пустой запрос показывает все товары
Проверьте: ?q=php, ?q=курс, пустой запрос, запрос без совпадений
Как понять, что упражнение решено хорошо
Решение должно работать не только на данных из примера. Проверьте пустой массив, одно значение, неправильное значение из формы, строку с HTML-тегом, ноль и отрицательное число там, где это возможно
Если код смешивает расчет и HTML, попробуйте разделить. Сначала подготовьте массив или число, затем отдельно выведите результат. Это простое правило помогает писать PHP-код, который легче поддерживать
Если задача связана с пользовательским вводом, задайте себе вопрос: что будет, если поле не пришло, пустое, содержит пробелы или HTML-теги. Если ответа нет, решение еще не готово
Частые ошибки в базовых PHP-упражнениях
- выводить значения из формы без
htmlspecialchars() - считать сумму корзины без учета количества
- забывать
?? ''при чтении из$_POSTи$_GET - не проверять пустой массив перед выводом списка
- делать функцию, которая одновременно считает, печатает HTML и читает форму
- использовать поиск без приведения регистра
- не проверять граничные страницы в пагинации
- писать весь код одним большим блоком без понятных переменных
Что собрать после упражнений
После этих задач попробуйте объединить их в один мини-каталог: массив товаров, фильтр по названию, таблица товаров, корзина из нескольких позиций и форма обратной связи. Это уже не большой проект, но он связывает базовые упражнения в рабочий сценарий