PHP: полный мануал с примерами, функциями и ООП
Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Дерево руководства
Глава 5 · С нуля → практика
Понятный код: имена, отступы и комментарии
Пишем так, чтобы через полгода было видно, откуда берутся данные и почему приняты решения.
Как записать маленький расчёт так, чтобы его прочитали
Задача — посчитать две упаковки чая по 150 рублей. Хорошее оформление позволяет увидеть цену, количество и результат ещё до чтения пояснения. Имя выбирайте по смыслу: $unitPriceRubles лучше $a, когда важно, что это цена одной штуки именно в рублях. В этих вводных примерах суммы целые; расчёт дробных денег отдельно разобран ниже.
<?php
$unitPriceRubles = 150;
$quantity = 2;
// В учебном каталоге цены целые; доставка считается отдельно.
$totalRubles = $unitPriceRubles * $quantity;
echo 'Товары: ', $totalRubles, " руб.\n";
Ожидаемый результат
Товары: 300 руб.
Пробелы вокруг = и * отделяют части выражения. Пустая строка отделяет исходные данные от расчёта. Комментарий объясняет допущение про цены и доставку, а не пересказывает умножение.
Одна инструкция — одна строка; внутри фигурных скобок используйте четыре пробела отступа. { } ограничивают блок, а отступ помогает человеку увидеть его. PHP не определяет вложенность количеством пробелов. Короткий комментарий начинается с //, многострочный — с /* и заканчивается */. Не прячьте старую программу в комментариях: историю хранит система контроля версий.
Попробуйте сами. Добавьте $deliveryRubles = 50 и назовите итог с доставкой.
Разбор решения
Например: $payableRubles = $totalRubles + $deliveryRubles; результат 350. Разные имена сохраняют различие между стоимостью товаров и суммой к оплате.
Дальше расчёт получает имя через собственную функцию. Затем вернитесь к разделам ниже: там форматирование, комментарии и PHPDoc применены к коду с ветвлениями и массивами.
Код читают чаще, чем пишут
Понятные имена оставляют маршрут для читателя
Через месяц нужно изменить расчёт корзины. Названия должны помогать найти данные, действие и результат без расшифровки каждой строки.
- 1$cartItems — позиции корзины↓
Имя объясняет, что за данные пришли в расчёт.
- 2calculateTotal() — посчитать итог↓
Имя функции называет выполняемое действие.
- 3$totalKopecks — итог в копейках
Имя результата дополнительно показывает единицу измерения.
Отступы показывают вложенность, пробелы разделяют части выражения. Комментарий объясняет причину: например, почему расчёт ведётся в копейках. Пересказывать очевидное действие каждой строки не нужно.
Представьте дежурство в магазине: покупателю начислена неверная скидка, и другой разработчик открывает ваш файл ночью. Название calculateDiscountKopecks объясняет больше, чем process2. Переменная $deliveryTimeoutSeconds показывает единицу измерения, $isPaid — логическое состояние, $orderIds — набор идентификаторов. Удачное имя сокращает число вопросов к автору. Не нужно механически делать каждое имя длинным: $index понятен в коротком цикле, но $data недостаточно для аргумента, где ожидается проверенный заказ.
Разделяйте получение данных, проверку, расчет и вывод. Функция расчета не должна незаметно читать $_POST или печатать HTML: иначе ее нельзя без изменений использовать в CLI-импорте или тесте. Начинайте с небольших функций по одной ответственности. Десяток строк, называющих бизнес-правило, обычно легче поддерживать, чем одно вложенное выражение на три строки.
Единый стиль без ручной борьбы с пробелами
PSR-12 задает распространенную основу: четыре пробела вместо табуляции, последовательное оформление скобок, пробелы у операторов, один оператор на строку. Сохраните UTF-8 без BOM, переносы LF и завершающий перевод строки. Для существующего проекта важнее согласованность с его стандартом; массовое переформатирование не смешивают с исправлением логики. Настройте форматтер в редакторе и проверку в CI, чтобы спор о пробелах не занимал ревью.
<?php
declare(strict_types=1);
function deliveryPriceKopecks(int $subtotalKopecks, bool $isPickup): int
{
if ($subtotalKopecks < 0) {
throw new InvalidArgumentException('Сумма не может быть отрицательной');
}
if ($isPickup || $subtotalKopecks >= 500000) {
return 0;
}
return 29900;
}
echo deliveryPriceKopecks(250000, false), "\n";
echo deliveryPriceKopecks(250000, true), "\n";
Ожидаемый результат
29900
0
Имя возвращаемого значения содержит копейки. Ранний return отделяет случаи бесплатной доставки; отрицательный ввод не маскируется. Скобки и пустая строка обозначают смысловые блоки, а не декоративные интервалы.
Комментарий объясняет причину и ограничение
Комментарий «увеличиваем счетчик» рядом с ++$count повторяет синтаксис. Полезнее: «поставщик считает повторную отправку новым заказом, поэтому используем сохраненный ключ идемпотентности». Пишите, какое внешнее ограничение или бизнес-решение объясняет необычный код. Ссылку на задачу добавляйте вместе с краткой причиной: одна ссылка теряет смысл после смены трекера. TODO должен содержать конкретное условие завершения, иначе он становится постоянной частью архитектуры.
<?php
declare(strict_types=1);
/**
* @param list<array{priceKopecks: int, quantity: int}> $items
* Скидка применяется к заказу целиком, чтобы сумма строк не расходилась с чеком.
*/
function subtotalKopecks(array $items): int
{
$subtotal = 0;
foreach ($items as $item) {
$subtotal += $item['priceKopecks'] * $item['quantity'];
}
return $subtotal;
}
echo subtotalKopecks([['priceKopecks' => 15000, 'quantity' => 3]]), "\n";
Ожидаемый результат
45000
PHPDoc помогает IDE и статическому анализатору, но сам PHP не проверяет внутреннюю форму массива по комментарию. Здесь вход уже нормализован; проверка внешнего JSON показана отдельно. Комментарий о скидке объясняет соседнее проектное решение, а не утверждает, что функция уже ее применяет.
Что проверять перед передачей кода
- Можно ли понять вход, результат и единицы измерения без просмотра всей программы?
- Отделены ли ошибки ввода от недоступности сервиса?
- Не скрывает ли короткое имя важное различие: сырой текст и безопасный HTML, ID и порядковый номер?
- Не остались ли закомментированные пароли, var_dump и отладочные выходы?
- Есть ли тест границы, а не только обычного числа?
Документируйте публичный контракт: исключения, допустимые диапазоны, изменение переданного объекта, побочные эффекты. Для стандартного int $count не требуется комментарий «целое число». Для массива строк поставщика полезна форма данных и объяснение, какие поля необязательны. Избыточные комментарии устаревают так же, как код; удаляйте неверное объяснение одновременно с изменением реализации.
Попробуйте сами. Переименуйте $t и $a в функции, которая ждет ответ API и ограничивает число повторов. Добавьте один полезный комментарий.
Разбор решения
$timeoutSeconds и $maxAttempts называют две разные величины. Комментарий может объяснять, почему предел 3 согласован с SLA поставщика. Комментарий «ждем указанное число секунд» не добавляет знания.
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


