heredoc и nowdoc
В прошлом уроке весь текст помещался в одну строчку кода. Но бланк бывает и многостраничным: письмо пользователю, кусок HTML-страницы, запрос к базе данных.
Писать такой текст в кавычках неудобно. В конце каждой строчки нужен \n, а каждую кавычку внутри приходится экранировать — ставить перед ней обратную косую черту, как в \". Для длинного текста в 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.Давайте разберём, как устроен блок:
<<<TEXTоткрывает его: три знака «меньше» и слово-метка. Метку выбирают сами, обычно заглавными буквами:TEXT,HTML,SQL.- Строчки ниже — сам текст. Переводы строк в нём настоящие, писать
\nне нужно. TEXT;на отдельной строчке закрывает блок. Метка та же, что после<<<, а точка с запятой завершает инструкцию.- Перевод строки перед закрывающей меткой в текст не входит, поэтому в
echoдобавлен"\n".
Метку ещё называют идентификатором блока.
heredoc: бланк на несколько строк
Такой блок называют heredoc. Внутри он работает как двойные кавычки:
- подставляет переменные, в том числе в фигурных скобках
{$name}; - обрабатывает
\n,\tи другие управляющие последовательности; - считает кавычки обычными символами:
He said "hi"пишется как есть, без\".
Для письма или HTML со значениями из переменных удобен heredoc.
nowdoc: многостраничная ксерокопия
Если взять метку в одинарные кавычки, получится nowdoc. Он работает как одинарные кавычки: ничего не подставляет и печатает текст буква в букву.
$raw = <<<'TEXT'
Hello, $name!\n
TEXT;
echo $raw, "\n"; // Hello, $name!\nКавычки нужны только у открывающей метки, а закрывает блок по-прежнему TEXT;. nowdoc берут для текста, где знак $ должен остаться знаком: примеры кода, шаблоны, запросы к базе данных.
Чем heredoc отличается от nowdoc, спрашивают на собеседовании. Ответ укладывается в одну фразу: heredoc ведёт себя как двойные кавычки, а nowdoc — как одинарные.
Отступ закрывающей метки
Блок часто стоит внутри кода с отступами. Закрывающую метку можно сдвинуть вправо вместе с кодом, и тогда PHP уберёт столько же пробелов из начала каждой строчки текста:
$html = <<<HTML
<p>
Hi, {$name}!
</p>
HTML;
echo $html, "\n";
// <p>
// Hi, Anna!
// </p>Разберём по шагам:
- Перед меткой
HTML;стоят четыре пробела. - PHP убирает по четыре пробела из начала каждой строчки текста.
- У строчки
Hi, {$name}!было шесть пробелов, и у неё остаются два.
Здесь бланк перестаёт быть точной картинкой. Отступ перед закрывающей меткой — правило блока, а не часть текста, и PHP вырезает его из каждой строчки. Так работают все версии PHP, начиная с 7.3.
Частая ошибка
Текст написали от левого края, а закрывающую метку выровняли вместе с кодом:
$text = <<<TEXT
Hello, $name!
TEXT; // ✗
echo $text, "\n";Parse error: Invalid body indentation level (expecting an indentation level of at least 4)PHP должен убрать четыре пробела из строчки, где их нет, и сообщает, что ждал отступ хотя бы в четыре пробела. Это ошибка разбора, поэтому не выполнится ни одна строка программы. Исправление — сдвинуть текст не меньше, чем стоит метка, или убрать отступ у метки.
Главное
- heredoc
<<<TEXT…TEXT;— многострочная строка, которая работает как двойные кавычки. - nowdoc
<<<'TEXT'работает как одинарные кавычки и ничего не подставляет. - Перевод строки перед закрывающей меткой в строку не входит.
- Отступ закрывающей метки PHP убирает из каждой строчки, а строчка с меньшим отступом — ошибка разбора.