Перейти к содержимому
Теория · Строки · урок 2 из 9

heredoc и nowdoc

В прошлом уроке весь текст помещался в одну строчку кода. Но бланк бывает и многостраничным: письмо пользователю, кусок HTML-страницы, запрос к базе данных.

Писать такой текст в кавычках неудобно. В конце каждой строчки нужен \n, а каждую кавычку внутри приходится экранировать — ставить перед ней обратную косую черту, как в \". Для длинного текста в PHP есть отдельная запись:

PHP
<?php

$name = 'Anna';
$count = 3;
$letter = <<<TEXT
Hello, $name!
You have $count new messages.
TEXT;
echo $letter, "\n";
// Hello, Anna!
// You have 3 new messages.

Давайте разберём, как устроен блок:

  1. <<<TEXT открывает его: три знака «меньше» и слово-метка. Метку выбирают сами, обычно заглавными буквами: TEXT, HTML, SQL.
  2. Строчки ниже — сам текст. Переводы строк в нём настоящие, писать \n не нужно.
  3. TEXT; на отдельной строчке закрывает блок. Метка та же, что после <<<, а точка с запятой завершает инструкцию.
  4. Перевод строки перед закрывающей меткой в текст не входит, поэтому в echo добавлен "\n".

Метку ещё называют идентификатором блока.

heredoc: бланк на несколько строк

Такой блок называют heredoc. Внутри он работает как двойные кавычки:

  • подставляет переменные, в том числе в фигурных скобках {$name};
  • обрабатывает \n, \t и другие управляющие последовательности;
  • считает кавычки обычными символами: He said "hi" пишется как есть, без \".

Для письма или HTML со значениями из переменных удобен heredoc.

nowdoc: многостраничная ксерокопия

Если взять метку в одинарные кавычки, получится nowdoc. Он работает как одинарные кавычки: ничего не подставляет и печатает текст буква в букву.

PHP
$raw = <<<'TEXT'
Hello, $name!\n
TEXT;
echo $raw, "\n"; // Hello, $name!\n

Кавычки нужны только у открывающей метки, а закрывает блок по-прежнему TEXT;. nowdoc берут для текста, где знак $ должен остаться знаком: примеры кода, шаблоны, запросы к базе данных.

Чем heredoc отличается от nowdoc, спрашивают на собеседовании. Ответ укладывается в одну фразу: heredoc ведёт себя как двойные кавычки, а nowdoc — как одинарные.

Отступ закрывающей метки

Блок часто стоит внутри кода с отступами. Закрывающую метку можно сдвинуть вправо вместе с кодом, и тогда PHP уберёт столько же пробелов из начала каждой строчки текста:

PHP
$html = <<<HTML
    <p>
      Hi, {$name}!
    </p>
    HTML;
echo $html, "\n";
// <p>
//   Hi, Anna!
// </p>

Разберём по шагам:

  1. Перед меткой HTML; стоят четыре пробела.
  2. PHP убирает по четыре пробела из начала каждой строчки текста.
  3. У строчки Hi, {$name}! было шесть пробелов, и у неё остаются два.

Здесь бланк перестаёт быть точной картинкой. Отступ перед закрывающей меткой — правило блока, а не часть текста, и PHP вырезает его из каждой строчки. Так работают все версии PHP, начиная с 7.3.

Частая ошибка

Текст написали от левого края, а закрывающую метку выровняли вместе с кодом:

PHP
$text = <<<TEXT
Hello, $name!
    TEXT; // ✗
echo $text, "\n";
TEXT
Parse error: Invalid body indentation level (expecting an indentation level of at least 4)

PHP должен убрать четыре пробела из строчки, где их нет, и сообщает, что ждал отступ хотя бы в четыре пробела. Это ошибка разбора, поэтому не выполнится ни одна строка программы. Исправление — сдвинуть текст не меньше, чем стоит метка, или убрать отступ у метки.

Главное

  • heredoc <<<TEXT … TEXT; — многострочная строка, которая работает как двойные кавычки.
  • nowdoc <<<'TEXT' работает как одинарные кавычки и ничего не подставляет.
  • Перевод строки перед закрывающей меткой в строку не входит.
  • Отступ закрывающей метки PHP убирает из каждой строчки, а строчка с меньшим отступом — ошибка разбора.