Heredoc & Nowdoc
Quoting a long block of text with single or double quotes gets ugly fast — every apostrophe needs escaping, every line break needs an explicit \n, and the whole thing turns into a wall of backslashes. PHP has two dedicated syntaxes for multi-line string literals: heredoc and nowdoc. Heredoc behaves like a double-quoted string that can span many lines without escaping; nowdoc behaves the same way but like a single-quoted string, meaning nothing inside it is interpolated. Both are built around a marker you choose yourself, so the string body can contain quotes, dollar signs, and anything else without a single backslash.
Heredoc syntax
A heredoc starts with <<< followed by an identifier (a bare word, no quotes), then a newline, then the text, then the same identifier on its own line to close it. Inside the body, variables are interpolated and escape sequences like \n and \t are processed exactly as they would be inside double quotes.
heredoc-basic.php
<?php $name = 'Ada'; $role = 'engineer'; $bio = <<<EOT Name: $name Role: $role Note: "Quotes" and it's apostrophes need no escaping here. EOT; echo $bio;
Name: Ada Role: engineer Note: "Quotes" and it's apostrophes need no escaping here.
The closing identifier, EOT in that example, is not a special keyword — you can name it anything as long as the opening and closing markers match. Convention favors short, shouty names like EOT, HTML, or SQL that hint at what the block contains.
Nowdoc syntax: the literal counterpart
Wrap the opening identifier in single quotes — <<<'EOT' — and you get a nowdoc instead. A nowdoc is to heredoc what a single-quoted string is to a double-quoted one: nothing inside it is interpolated. Variables are printed as literal text and backslash sequences are left alone. Reach for a nowdoc when the block itself contains PHP-looking syntax, such as example code or a shell script, that you don't want PHP to touch.
nowdoc-basic.php
<?php $price = 42; $template = <<<'EOT' This is a literal $price and it will not be replaced. Backslashes like stay exactly as typed. EOT; echo $template;
This is a literal $price and it will not be replaced. Backslashes like \n stay exactly as typed.
Flexible closing-marker indentation (PHP 7.3+)
Before PHP 7.3, the closing identifier had to start at column zero, which forced you to break indentation inside a nicely nested block of code just to satisfy the heredoc — ugly, and it invited accidental whitespace bugs. PHP 7.3 introduced flexible heredoc/nowdoc syntax: the closing marker can now be indented to match the surrounding code, and PHP strips that same amount of leading whitespace from every line of the body.
flexible-indentation.php
<?php
function buildGreeting(string $name): string
{
$message = <<<EOT
Hello, $name!
Welcome aboard.
EOT;
return $message;
}
echo buildGreeting('Grace');Hello, Grace! Welcome aboard.
Here the closing EOT; is indented four spaces, and PHP removes exactly four spaces of leading whitespace from each line of the body before storing the string — the indentation used purely for readability in the source file never ends up in the actual value.
Interpolating expressions and arrays
Because a heredoc interpolates like a double-quoted string, the same
curly-brace syntax for complex expressions works inside it —
{$obj->property} or {$arr['key']} — which is useful when the
text mixes plain variables with property or array access.
heredoc-expressions.php
<?php
$user = ['name' => 'Tariq', 'plan' => 'Pro'];
$summary = <<<EOT
User: {$user['name']}
Plan: {$user['plan']}
EOT;
echo $summary;User: Tariq Plan: Pro
Practical use cases
Heredoc shines anywhere you're assembling a large chunk of templated text — an HTML fragment, an email body, or a multi-line SQL query — where mixing in variables via string concatenation would be tedious to read. Nowdoc is the better fit when the block is closer to a raw file, such as a code sample, a config template, or a snippet with literal $ signs that must survive untouched.
sql-template.php
<?php $table = 'orders'; $status = 'shipped'; $sql = <<<SQL SELECT id, customer_id, total FROM $table WHERE status = '$status' ORDER BY created_at DESC SQL; echo $sql;
SELECT id, customer_id, total FROM orders WHERE status = 'shipped' ORDER BY created_at DESC
Heredoc (
<<<EOT) interpolates variables and escape sequences, just like double quotes.Nowdoc (
<<<'EOT') is fully literal, just like single quotes.The opening and closing identifiers must match exactly; the closing one must sit alone on its line (plus optional indentation).
PHP 7.3+ lets you indent the closing marker, and strips that same leading whitespace from every body line.
Both are ideal for multi-line SQL, HTML, or text templates where escaping quotes would otherwise be painful.