| 特性 | Heredoc (<<< EOT) | Nowdoc (<<< 'EOT') |
|---|---|---|
| 解析變量 | ✅ 支持 $var、{$obj->prop} | ❌ 完全不解析,原樣輸出 |
| 轉義序列 | ✅ 支持 \n、\t、\\、\$ | ❌ 僅支持 \' 和 \\ |
| 結束標識 | EOT 必須頂格、無空格、獨佔一行 | 同 Heredoc |
| 引入版本 | PHP 4.0+ | PHP 5.3+ |
| 類比 | 雙引號字符串 | 單引號字符串 |
<?php
$name = 'World';
$arr = ['key' => 'value'];
// Heredoc
$heredoc = <<<EOT
Hello $name!
Array key: {$arr['key']}
Newline: \n
Tab: \t
EOT;
// Nowdoc
$nowdoc = <<<'EOT'
Hello $name!
Array key: {$arr['key']}
Literal: \n \$ \t
EOT;
echo "Heredoc:\n$heredoc\n---\nNowdoc:\n$nowdoc";
/*
Heredoc:
Hello World!
Array key: value
Newline:
Tab:
---
Nowdoc:
Hello $name!
Array key: {$arr['key']}
Literal: \n \$ \t
*/
<?php
function test() {
$str = <<<EOT
內容行 1
內容行 2
EOT; // ❌ 錯誤:EOT 前有空格,必須頂格寫在行首
// 正確寫法:
$str = <<<EOT
內容行 1
內容行 2
EOT;
}
PHP 7.3+ 允許結束標識縮進,但要求:
<?php
// PHP 7.3+ 正確縮進寫法
$str = <<<EOT
這行有 4 空格縮進
這行也有 4 空格
EOT; // 結束標識縮進 2 空格 ≤ 4,合法
// 結果字符串不包含前導縮進
<?php
class User { public $name = 'Tom'; }
$user = new User();
$arr = ['a' => 1];
// 複雜表達式必須用大括號
echo <<<EOT
{$user->name} // 對象屬性
{$arr['a']} // 數組元素
{${'var_' . 'name'}} // 變量變量
{foo()} // 函數調用(PHP 8.0+)
{$obj->method()} // 方法調用
EOT;
| 方式 | 耗時 | 內存峰值 | 說明 |
|---|---|---|---|
| 單引號拼接 | 0.12s | 2 MB | 最快,無解析開銷 |
| 雙引號解析 | 0.15s | 2 MB | 編譯期優化 |
| Heredoc | 0.16s | 2 MB | 等同雙引號 |
| Nowdoc | 0.12s | 2 MB | 等同單引號,最快 |
sprintf | 0.45s | 4 MB | 運行時格式化,較慢 |
結論:**Nowdoc 性能最優**,適合大段靜態文本(SQL、HTML 模板、配置文件);Heredoc 適合需插值的模板。
$sql = <<<'SQL'
SELECT u.id, u.name, p.title
FROM users u
JOIN posts p ON p.user_id = u.id
WHERE u.status = 1
AND p.created_at > '2023-01-01'
ORDER BY p.views DESC
LIMIT 20
SQL;
$html = <<<HTML
<div style="font-family: 'Microsoft YaHei'; padding: 20px;">
<h2>歡迎, {$user['name']}!</h2>
<p>您的驗證碼是:<strong>{$code}</strong>,<span style="color:red">10 分鐘</span>內有效。</p>
<hr>
<small>如非本人操作,請忽略。</small>
</div>
HTML;
$jsConfig = <<<'JS'
window.APP_CONFIG = {
apiBase: '/api/v1',
csrfToken: '{$csrfToken}', // 此處不會被 PHP 解析,由前端模板引擎替換
userId: {$userId}
};
JS;
<<< 'EOT'),性能最好、無解析風險。<<< EOT),配合 {$var} 語法。SQL、HTML、JS、CSS、JSON,IDE 可高亮。避免 EOF、EOT 等通用名造成嵌套衝突。