PHPHeredoc & Nowdoc

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
<?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
<?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
<?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.

The closing marker's indentation is the rule
Whatever amount of whitespace precedes the closing identifier is stripped from every body line. If a body line has less leading whitespace than the closing marker, PHP raises a `ParseError` at compile time — it can't strip more than that line actually has.
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
<?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
<?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 (&lt;&lt;&lt;EOT) interpolates variables and escape sequences, just like double quotes.

  • Nowdoc (&lt;&lt;&lt;'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.

Tip
When a heredoc body needs to embed something that looks like SQL, HTML, or JSON, give your editor a fighting chance at syntax highlighting by naming the identifier after the content — `<<<HTML` or `<<<SQL` — many editors and IDEs pick up on the convention and highlight the block accordingly.