PHP で複数行にわたる長い文字列、たとえばメール本文や HTML のかたまりを書こうとすると、引用符のエスケープや改行の連結が増えて読みにくくなりがちです。そんなときに便利なのがヒアドキュメント(heredoc)とnowdocです。引用符で囲まなくても複数行の文字列をそのまま書け、heredoc では変数の埋め込みもできます。この記事では、heredoc と nowdoc の書き方、2つの違い、HTML やメール文での活用例、つまずきやすい終了識別子のルールまで、初心者の方にも分かるように解説します。
目次
ヒアドキュメント(heredoc)とは
heredoc は、<<< に続けて終了識別子(任意の名前)を書き、その識別子で囲んだ範囲を1つの文字列として扱う書き方です。ダブルクォートで囲んだ文字列と同じように働き、変数を埋め込めるのが特徴です。改行や引用符をそのまま書けるため、長い文章を読みやすく記述できます。
<?php
$name = "山田";
$message = <<<EOT
$name さん、こんにちは。
ご登録ありがとうございます。
"引用符" もそのまま書けます。
EOT;
echo $message;
// 山田 さん、こんにちは。
// ご登録ありがとうございます。
// "引用符" もそのまま書けます。
EOT の部分は自分で決められる名前で、慣習的に EOT(End Of Text)や HTML、SQL などが使われます。開始の <<<EOT と、終了の EOT; で内容を挟むだけです。ダブルクォートのエスケープが不要になるため、引用符を多く含む文章で特に効果を発揮します。
nowdoc とは
nowdoc は heredoc とよく似ていますが、終了識別子をシングルクォートで囲む点が違います(<<<'EOT')。そして最大の違いは、変数を展開しないことです。シングルクォートの文字列と同じように、書いた内容がそのまま文字列になります。
<?php
$name = "山田";
$text = <<<'EOT'
$name はそのまま表示されます。
変数は展開されません。
EOT;
echo $text;
// $name はそのまま表示されます。
// 変数は展開されません。
コード例やテンプレートの雛形など、$ を含む文字列をそのまま出力したいときは nowdoc が向いています。「変数を埋め込みたいなら heredoc、文字どおり出したいなら nowdoc」と覚えておきましょう。
heredoc と nowdoc の違い
2つの違いを整理すると、ダブルクォート文字列とシングルクォート文字列の関係によく似ています。
| 項目 | heredoc | nowdoc |
|---|---|---|
| 開始の書き方 | <<<EOT | <<<'EOT' |
| 変数の展開 | される | されない |
| 近い文字列 | ダブルクォート "..." | シングルクォート '...' |
HTML やメール本文での活用
heredoc が活躍する代表例が、変数を含む HTMLの組み立てです。通常の文字列連結だと引用符とドットが入り混じって読みにくくなりますが、heredoc なら HTML をそのままの形で書けます。波カッコ {$変数} で囲むと、配列の要素やオブジェクトのプロパティも確実に展開できます。
<?php
$title = "新商品のお知らせ";
$url = "https://example.com/news";
$html = <<<HTML
<div class="card">
<h2>{$title}</h2>
<a href="{$url}">詳しく見る</a>
</div>
HTML;
echo $html;
なお、HTML として出力するときは、変数の中身が利用者の入力などを含む場合があります。その際は埋め込む前に htmlspecialchars() でエスケープし、安全に出力するようにしましょう。
終了識別子のルール
heredoc / nowdoc で初心者がつまずきやすいのが、終了識別子の書き方です。次のルールを守らないと構文エラーになります。
まず、開始と終了の識別子は同じ名前にします。そして終了行は、識別子のあとに ; を付ける程度で、余計な文字を続けて書けません。PHP 7.3 以降では終了識別子をインデント(字下げ)できるようになり、その字下げ分は各行の先頭から自動的に取り除かれます。これにより、コードのインデントに合わせて見やすく書けます。
<?php
function greet($name) {
// PHP 7.3 以降は終了識別子を字下げできる
return <<<EOT
$name さん、こんにちは。
本日もよろしくお願いします。
EOT;
}
// 終了識別子の字下げ分(空白)は各行から取り除かれる
構文エラーが出るときの確認点
終了行に余計な文字がある
古い書き方の名残で「終了識別子は行頭に置き、後ろに ; 以外を書けない」と覚えている方も多いでしょう。PHP 7.3 以降は字下げが可能になりましたが、それでも終了識別子の直後に文字を続けることはできません。エラーが出るときは、終了行に余分な空白以外の文字やコメントが付いていないか確認してください。
本文より深く字下げしている
PHP 7.3 以降のインデント機能では、終了識別子の字下げが、本文のどの行よりも深いとエラーになります。終了識別子のインデントは、本文の中で最も浅い行と同じか、それより浅くする必要があります。位置を揃えるときはこの点に注意しましょう。
まとめ
heredoc と nowdoc は、複数行の文字列を読みやすく書くための構文です。要点を整理します。
- heredoc は
<<<EOT ... EOT;。ダブルクォート相当で変数が展開される。 - nowdoc は
<<<'EOT' ... EOT;。シングルクォート相当で展開されない。 - 変数を含む HTML やメール本文を、引用符のエスケープなしで書ける。
- 配列・プロパティは
{$変数}で囲むと確実に展開できる。 - PHP 7.3 以降は終了識別子を字下げ可能。本文より深い字下げはエラー。
長い文字列の連結が読みにくいと感じたら、heredoc に置き換えてみてください。変数の埋め込みが不要で文字どおり出したい場合は nowdoc、と使い分けると、文字列まわりのコードがぐっとすっきりします。