Перейти к содержимому
Поиск
Php Разработка

PHP: полный мануал с примерами, функциями и ООП

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

Александр НекрасовИзменено:
Практический мануал PHP: от переменных и функций к объектной модели интернет-магазина
PHP 8.5.11149 глав4458 карточек справочника
Дерево руководства

Глава 6 · С нуля

Базовый синтаксис PHP: теги, инструкции, HTML и комментарии

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

Первый код: что PHP выполняет, а что получает читатель

Наглядная модель

Из исходника в видимый текст

В первом примере есть одна команда: echo 'Магазин открыт'. Посмотрим, что переходит между этапами.

  1. Файл example.php

    <?php открывает код; echo просит вывести строку 'Магазин открыт'.

  2. PHP выполняет echo

    Тег, кавычки и ; описывают команду. Её результат — текст Магазин открыт.

  3. Выход: Магазин открыт

    В консоли текст виден сразу. В веб-запросе он входит в тело ответа для браузера.

Это путь данных, а не устройство памяти и не полная схема HTTP. Тело ответа может буферизоваться; браузер PHP не выполняет.

Нужно вывести сообщение магазина. Начнём с одного файла: без переменных, функций, циклов и настроек базы данных. Сохраните пример как example.php в кодировке UTF-8 без BOM и запустите через PHP, как показано в первых шагах. Открытие исходного файла как обычного текста не запускает программу.

PHP читает исходник и выполняет команды в PHP-области. Команда echo добавляет текст в выходной поток. В консоли вы увидите этот текст; при правильно настроенном веб-сервере он станет частью тела HTTP-ответа. Браузер получает результат, а не выполняет этот PHP-код.

Сообщение без переменныхСамостоятельный пример
<?php
echo 'Магазин открыт';
Ожидаемый результат
Магазин открыт

Магазин открыт — полезный результат. Теги PHP, слово echo, кавычки и точка с запятой в него не попадают.

Разбираем каждый знак: тег, echo, кавычки и ;

Часть первой строкиКак читать
<?phpНачало PHP-области. После php нужен пробел, табуляция или перенос строки; слово echo нельзя приклеивать к тегу.
echo«Выведи следующие значения». Это конструкция языка; круглые скобки для неё не нужны.
'Магазин открыт'Строка: буквальный текст между парными прямыми кавычками. Кавычки ограничивают значение, но сами не выводятся.
;Конец этой инструкции. Перенос строки в редакторе его не заменяет.

Текстовые редакторы иногда заменяют прямые кавычки на типографские «ёлочки». В коде строку ограничивают ' или ". Одиночная и двойная кавычки не образуют пару. Двойные кавычки умеют специальные записи: "\n" означает перевод строки, а в одинарных '\n' остаются два символа — обратная косая черта и n.

echo не вставляет пробелы и переводы строк сам. Запятая разделяет выводимые значения: можно передать сначала подпись, затем число. Это список для echo, а не новая инструкция.

Собираем две строки выводаСамостоятельный пример
<?php
echo 'Заказ: ', 17, "\n";
echo 'Статус: новый', "\n";
Ожидаемый результат
Заказ: 17
Статус: новый

Число 17 записано без кавычек. Перед выводом echo представляет его текстом. Переводы строк мы добавили явно. В HTML обычный перевод строки не означает тег <br>; браузер обычно сворачивает такой пробельный текст.

Попробуйте сами. Уберите пробел после двоеточия внутри первой строки. Добавит ли echo его обратно?

Разбор решения

Нет: получится Заказ:17. Пробел внутри кавычек — часть данных.

Полный тег, короткий вывод и старые формы

Для файлов приложения используйте <?php. В HTML-шаблоне удобно <?= значение ?>: знак = здесь является частью тега и означает сокращённый echo. Это не присваивание переменной. Начиная с PHP 5.4, короткий вывод доступен независимо от short_open_tag; во всей базе примеров PHP 8.2+ это правило уже действует.

Форма <? без php зависит от настройки short_open_tag и сборки PHP. На другом сервере такой участок может превратиться в обычный вывод. Для переносимого кода она не нужна; не путайте её с <?=. XML-декларация тоже начинается с <?, поэтому короткие теги могут создавать конфликт.

Значение внутри HTML-абзацаСамостоятельный пример
<?php ?>
<p>Товаров: <?= 3 ?></p>
Ожидаемый результат
<p>Товаров: 3</p>

Пустая PHP-область в первой строке ничего не выводит. Её можно убрать: сам шаблон вправе начинаться сразу с <p>. После тега <?= PHP выводит число 3, затем снова отдаёт HTML.

Запись в старом проектеСтатус и замена
<? echo ... ?>Зависит от short_open_tag; заменить на полный тег.
<% ... %>, <%= ... %>ASP-теги удалены в PHP 7.0. Не являются PHP-разделителями в современном коде.
<script language="php">...</script>Эта историческая PHP-форма удалена в PHP 7.0. Замена — полный PHP-тег; это не JavaScript.

Наличие расширения .php само по себе не настраивает сервер. Если исходник выдаётся целиком, проверяйте обработчик PHP в окружении. Исторические версии здесь нужны для чтения старого кода; выполнять примеры следует на поддерживаемой ветке.

Смешанный файл: исходник → выполнение → HTML

За пределами PHP-тегов обычный текст передаётся в результат. Слова «PHP его игнорирует» означают: не разбирает как PHP-команды. Они не означают «выбрасывает из ответа». Несколько PHP-областей одного файла продолжают одну программу.

Шаблон с постоянным заголовком и вычисляемым остаткомСамостоятельный пример
<?php ?>
<h1>Самовывоз</h1>
<p>Свободных мест: <?php echo 4 + 2; ?></p>
<p>Выдача до 20:00</p>
Ожидаемый результат
<h1>Самовывоз</h1>
<p>Свободных мест: 6</p>
<p>Выдача до 20:00</p>

4 + 2 вычисляется в PHP и даёт 6. Теги h1 и p остаются в ответе; браузер использует их для оформления. В CLI виден именно HTML-текст.

Три участка одного результата
  1. Статический HTML: заголовок и начало абзаца передаются как текст.
  2. PHP-участок: сложение даёт 6; echo добавляет эту цифру.
  3. Оставшийся HTML: закрывается абзац и выводится время выдачи.

PHP не проверяет правильность HTML. Можно получить корректную PHP-программу, которая создаёт незакрытый HTML-тег. Проверка php -l проверяет синтаксис PHP, а вёрстку результата нужно отдельно открыть в браузере. Для длинного неизменного HTML выход из PHP-режима обычно понятнее десятков echo; это также позволяет не разбирать весь статический текст как PHP-строки. Из этого не следует обещание заметного ускорения всего сайта.

Инструкции, переносы и пробелы

Инструкция — законченная команда программы. Две инструкции можно поставить в одной физической строке, разделив ;, но по одной на строку читать легче. Одну инструкцию можно перенести на несколько строк: её завершит ;, а не Enter.

Пробелы между частями кода обычно разделяют слова и улучшают чтение. Нельзя разорвать ключевое слово echo или многосимвольный оператор. Пробелы внутри строки и вне PHP-области уже являются данными и могут попасть в результат.

Разное форматирование, один смыслСамостоятельный пример
<?php
echo 'A'; echo 'B';
echo
    'C',
    "\n";
echo 'A B', "\n";
Ожидаемый результат
ABC
A B

Первые три инструкции выводят ABC без пробелов. Во второй строке результата пробел находится внутри строки 'A B', поэтому сохранён. Отступы в PHP-коде не вставляют отступы в вывод.

Используйте четыре пробела для отступа и не смешивайте табуляции с пробелами в одном проекте. Это договорённость оформления, а не требование парсера. Имена, комментарии и форматирование подробно разобраны в правилах читаемого кода.

Что закрывает ;, что закрывает } и что делает ?>

Внутри PHP пишите ; после echo, присваивания и других простых инструкций. Закрывающий PHP-тег ?> может завершить последнюю инструкцию без отдельной точки с запятой. Но конец файла без такого тега не заменяет ;.

Фигурные скобки { ... } группируют команды в блок. Например, if (true) означает «если условие истинно»; true — логическое «да». Внутри блока echo всё равно требует ;. Сам завершённый блок if не требует добавлять точку с запятой после }. Это не универсальное правило для всех конструкций со скобками: например, присваивание функции-замыкания заканчивается ;.

Точка с запятой внутри блокаСамостоятельный пример
<?php
if (true) {
    echo 'Пункт выдачи открыт', "\n";
}
echo 'Продолжаем работу', "\n";
Ожидаемый результат
Пункт выдачи открыт
Продолжаем работу

Круглые скобки содержат условие; фигурные — выполняемые при true команды. } заканчивает группу, но не исправляет пропущенный ; после echo.

Закрывающий тег поглощает один следующий переносСамостоятельный пример
<?php echo 'A' ?>
B
<?php echo 'C'; ?>D
Ожидаемый результат
AB
CD

Первый перевод строки стоит сразу после ?> и включён в закрывающий тег: A и B склеиваются. Перевод после B — уже обычный текст, поэтому сохраняется. Чтобы получить перевод после A, нужно вывести его явно.

Явный перенос не теряетсяСамостоятельный пример
<?php echo "A\n"; ?>
B
Ожидаемый результат
A
B

Теперь перенос является частью строки, которую вывел echo. Независимо от следующего PHP-тега он уже находится в результате.

Комментарии: //, # и /* ... */

Комментарий нужен читателю исходника; PHP не выполняет его содержимое как код. // и # действуют до конца текущей строки или до закрывающего PHP-тега. /* ... */ охватывает несколько строк и заканчивается на первом */.

Пишите причину неочевидного решения: «время приведено к часовому поясу склада», а не «выводим текст». /** ... */ — тоже блочный комментарий; дополнительную структуру PHPDoc могут читать редактор и инструменты документации.

Три формы комментарияСамостоятельный пример
<?php
// Объявление показываем до открытия приёма заказов.
echo 'Заказы с 09:00', "\n";
# Внутренняя подсказка разработчику.
/* Текст хранится здесь временно:
   позже его заменит настройка магазина. */
echo 'https://shop.example/help', "\n";
Ожидаемый результат
Заказы с 09:00
https://shop.example/help

В адресе внутри кавычек // является частью строки, не комментарием. Код в комментарии не нужно считать резервным хранилищем старых версий — для истории изменений удобнее Git.

Не вкладывайте один блочный комментарий в другой: первый */ завершает весь текущий комментарий. В PHP 8.0+ последовательность #[ открывает атрибут, поэтому она не годится как начало обычного комментария. Сам атрибут — метаданные объявления, о нём есть отдельный раздел. Для обычной заметки используйте // или # с пробелом.

Граница комментария может стать границей ответа

Ловушка: ?> завершает однострочный комментарийСамостоятельный пример
<?php
// echo 'Эта команда закомментирована'; ?>Но этот текст выведется.
Ожидаемый результат
Но этот текст выведется.

Это намеренно показанный неожиданный, но допустимый синтаксис. PHP увидел закрывающий тег внутри однострочного комментария. Всё после него уже обычный текст. Для отключения большого участка выбирайте строки без закрывающего тега или аккуратный блочный комментарий без вложенности.

В блочном комментарии закрывающий тег — текстСамостоятельный пример
<?php
/* Пример разделителя: ?>. Комментарий продолжается до звёздочки со слешем. */
echo 'Выведено только это', "\n";
Ожидаемый результат
Выведено только это

Та же последовательность внутри /* ... */ не завершает PHP-область. Не переносите это правило на // и #.

HTML-комментарий не отключает вложенный PHPСамостоятельный пример
<?php ?>
<!-- Служебная метка: <?php echo 'demo-17'; ?> -->
<p>Витрина</p>
Ожидаемый результат
<!-- Служебная метка: demo-17 -->
<p>Витрина</p>

Браузер обычно не рисует HTML-комментарий, но он есть в полученном исходнике. PHP внутри него уже выполнился на сервере. Поэтому HTML-комментариями нельзя скрывать пароли или отключать PHP-команды. Здесь использована только демонстрационная метка.

Условный HTML: почему часть текста не отправляется

Условие управляет не только echo. Оно может окружать целый HTML-участок. if (false): начинает ветку для логического «нет», else: — альтернативу, endif; завершает условие. Двоеточие здесь заменяет открывающую фигурную скобку, а endif — закрывающую. В одном блоке формы не смешивают.

Сначала условие без переменныхСамостоятельный пример
<?php if (false): ?>
<p>Принимаем заказ</p>
<?php else: ?>
<p>Приём временно закрыт</p>
<?php endif; ?>
Ожидаемый результат
<p>Приём временно закрыт</p>

Обычный HTML первой ветки не попал в ответ. Он расположен вне PHP-тегов, но внутри false-ветки. Поменяйте false на true: будет выбран другой абзац.

В настоящем шаблоне условие приходит из данных. $stock — переменная, то есть имя текущего значения; = сохраняет в неё число; > 0 проверяет, больше ли оно нуля. Это весь новый синтаксис следующего примера. Подробнее — переменная по шагам.

Витрина показывает только подходящую кнопкуСамостоятельный пример
<?php
$stock = 2;
?>
<?php if ($stock > 0): ?>
<button type="button">Добавить в корзину</button>
<?php else: ?>
<p>Сообщим о поступлении</p>
<?php endif; ?>
Ожидаемый результат
<button type="button">Добавить в корзину</button>

Это демонстрация выбора HTML, а не реализация корзины. Кнопка сама не меняет остаток. При оформлении заказа сервер должен заново проверить наличие товара; исчезнувшая кнопка не защищает обработчик.

Альтернативная запись также существует у while, for, foreach, switch и declare. У switch между его началом и первым case нельзя случайно вывести HTML или пробелы. Для этих конструкций есть разбор альтернативных шаблонов.

Первое значение из данных: вставляем текст безопасно

Название товара меняется, шаблон остаётся тем же. Сохраним название в $title. Сырые символы < и & имеют смысл для HTML; при вставке обычного текста их нужно закодировать. PHP-теги и <?= сами такую защиту не добавляют.

htmlspecialchars(...) — вызов готовой функции: значения в круглых скобках передаются ей, результат подставляется на место вызова. Первое значение — текст; ENT_QUOTES включает обработку обоих видов кавычек, ENT_SUBSTITUTE задаёт замену недопустимых последовательностей, символ | объединяет эти флаги, 'UTF-8' задаёт кодировку. Здесь функцию применяем к тексту внутри HTML-элемента, не к JavaScript или URL.

Название товара остаётся текстомСамостоятельный пример
<?php
$title = 'Чай <Особый> & мёд';
?>
<h1><?= htmlspecialchars($title, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?></h1>
Ожидаемый результат
<h1>Чай &lt;Особый&gt; &amp; мёд</h1>

Ожидаемый результат показывает исходный HTML. В браузере читатель увидит название «Чай <Особый> & мёд»; угловые скобки останутся буквальными символами, не HTML-тегом. Кодирование текста не проверяет его деловой смысл.

В функцию можно передать и другую строку; изменение товара не требует переписывать h1. Следующие ступени: как вызов получает данные и возвращает результат, кодирование для разных контекстов.

Файл только с PHP: почему лучше закончить без ?>

В файле с функциями или настройками вывод часто вообще не нужен. Оставьте его в PHP-режиме до конца: открывающий тег есть, закрывающего нет. Пробел после закрывающего тега, пустая строка или BOM до открывающего могут стать неожиданными байтами ответа. BOM — служебная метка кодировки в начале файла; для этих UTF-8-исходников выбирайте сохранение без неё.

Это особенно заметно, когда другой файл подключается через require: команда читает указанный файл и выполняет его в текущей программе. Путь __DIR__ . '/settings.php' соединяет каталог текущего файла и постоянное имя. __DIR__ — встроенная константа пути, точка — соединение строк. Имя файла в примере не приходит от посетителя.

Подключение файла без лишнего выводаСамостоятельный пример
<?php
echo '[';
require __DIR__ . '/settings.php';
echo ']', "\n";
Ожидаемый результат
[]

В архиве примера есть settings.php с одним комментарием и без закрывающего тега. Он ничего не выводит. Квадратные скобки нужны только как видимая рамка результата.

Тот же вызов, но после ?> остался пробелСамостоятельный пример
<?php
echo '[';
require __DIR__ . '/settings.php';
echo ']', "\n";
Ожидаемый результат
[ ]

В приложенном файле после ?> намеренно стоит один пробел. Его видно между скобками. Исправление — убрать закрывающий тег и всё после него в файле, который содержит только PHP.

В HTTP ранний вывод может помешать отправить заголовки и cookie, если они ещё не буферизованы. Буферизация меняет момент отправки, но не отменяет существование лишних байтов. Объяснение — тело и заголовки ответа и буфер вывода. Обычный перенос строки в конце файла без закрывающего PHP-тега остаётся PHP-пробелом и не выводится.

Синтаксическая ошибка: ищем причину, а не только отмеченную строку

До выполнения PHP разбирает синтаксис файла. Если парсер не может понять инструкцию, её код не является рабочим примером. Команда php -l example.php проверяет синтаксис без выполнения тела. Она не доказывает, что функция существует, данные допустимы или результат верен.

Сообщение часто указывает токен, на котором разбор окончательно сломался: пропущенный ; на предыдущей строке может проявиться на следующем echo. Проверяйте парность кавычек и скобок, затем конец предыдущей инструкции. Точный текст диагностики зависит от версии.

Нерабочий фрагмент: отсутствует ;Фрагмент или команда
<?php
echo 'Сборка'
echo 'Готово';

Намеренно запрещённый синтаксис, не готовая программа. Проверка PHP 8.5.11 сообщает unexpected token "echo". Добавьте ; после первой строки echo.

Нерабочий фрагмент: вложенный /* */Фрагмент или команда
<?php
/* временно отключено
   /* внутренняя заметка */
*/
echo 'Готово';

Намеренно запрещённый синтаксис. Первый */ уже закрыл комментарий; второй встретился как код. В PHP 8.5.11 диагностика содержит unexpected token "*". Отключайте строки через //, не вкладывайте блочные комментарии.

Отдельная точка с запятой — допустимая пустая инструкция. Именно поэтому нельзя автоматически ставить её сразу после if (...): условие тогда управляет пустотой, а следующий блок становится самостоятельным. Это ошибка смысла, которую lint не найдёт.

Допустимый антипаттерн: лишний ; после ifСамостоятельный пример
<?php
if (false);
{
    echo 'Этот блок всё равно выполняется', "\n";
}
Ожидаемый результат
Этот блок всё равно выполняется

Это намеренная демонстрация ошибки, не рекомендуемый стиль. Уберите ; сразу после if (false): тогда фигурный блок станет телом условия и вывода не будет.

Соберите небольшое сообщение и проверьте границы

Попробуйте сами. Сделайте HTML-заголовок «Доставка». Под ним выведите абзац «Стоимость: 250 ₽», вычислив 200 + 50 в PHP. В результате не должно быть видимых PHP-тегов.

Разбор решения
Решение: постоянный HTML и вычислениеСамостоятельный пример
<?php ?>
<h1>Доставка</h1>
<p>Стоимость: <?= 200 + 50 ?> ₽</p>
Ожидаемый результат
<h1>Доставка</h1>
<p>Стоимость: 250 ₽</p>

Шаблон оставляет HTML читаемым. Только вычисляемое значение находится внутри PHP-тегов.

Попробуйте сами. Добавьте комментарий с причиной временной цены. Он должен быть виден в исходном PHP, но не в HTML-ответе.

Разбор решения

Например, внутри PHP-области: // Цена действует для учебного маршрута. Не заменяйте его HTML-комментарием.

Дальше: сохранять меняющиеся значения, понимать вычисление выражений, выбирать ветки и повторять действия.

Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.