Menu

PHP Heredoc 和 Nowdoc:多行字符串

PHP heredoc 是以 <<<EOT 开头、以 EOT 结尾的多行字符串,它会像双引号字符串一样替换变量。nowdoc(<<<'EOT')则原样保留文本。本文讲解语法、缩进规则、在其中插入数组和对象,以及 HTML 模板。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

heredoc 是一种多行字符串。以 <<<EOT 开头,在接下来的几行写文本,最后在单独一行写 EOT; 结束。其中的变量会像在双引号字符串中一样被替换。

标识符(这里是 EOT)由一个字母或下划线开头,后面跟字母、数字或下划线。人们通常选一个能说明文本内容的名字:HTML、SQL、TEXT。当名字是 HTML 或 SQL 时,一些编辑器(包括 PhpStorm)会把正文按对应的语言高亮。

用 heredoc 构建 HTML 模板

要写一段带有变量值的 HTML,heredoc 是最清晰的方式,因为标记能保持原有的结构,而且什么都不用转义。输出是 HTML,所以编辑器会在“页面”标签页中显示它。

这段代码有两个细节:数组元素用花括号括起来,{$product['name']};价格前面的美元符号是字面量,转义为 \$。改一下名字或者加一个标签,再运行一次。

来自用户的值在放进 HTML 之前必须转义。原因和做法见 htmlspecialchars。

Nowdoc:不做插值的文本

nowdoc 把标识符放在单引号里:<<<'EOT'。其中的内容不会被替换,美元符号和反斜杠都原样保留。代码示例、正则表达式以及任何包含 $ 的文本都适合用它。

缩进结束标记

从 PHP 7.3 开始,结束标记可以缩进,并且这段缩进会从正文的每一行中去掉。这样,函数或 if 中的 heredoc 就能跟随代码的缩进,而这些空格不会出现在字符串里。

json_encode 这一行让结果的每个字符都清晰可见:每一行都去掉了 8 个空格,因为结束的 TEXT; 缩进了 8 个空格。

如果正文某一行的缩进少于结束标记,就是解析错误:

$html = <<<HTML
  <p>Hello</p>
    HTML;
PHP Parse error:  Invalid body indentation level (expecting an indentation level of at least 4) in /home/index.php on line 3

在 heredoc 中使用数组、对象和方法调用

heredoc 遵循和双引号相同的规则。简单变量可以直接写;带引号的数组键、嵌套数组、属性和方法调用则要用花括号。

把 heredoc 作为函数参数

从 PHP 7.3 开始,结束标记后面可以在同一行继续写代码,所以 heredoc 可以直接传给函数,或者放进数组里。配合 sprintf,你就得到一个占位符稍后再填充的模板。

常见错误:缺少分号或标记后多了字符

结束标识符必须和开头写得完全一样(大小写也相同),并且同一行中它后面的内容必须是合法的 PHP。EOT; 结束一条语句,EOT, 则继续一个参数列表。如果标记后面紧跟字母或数字(EOTX;),标记就不再被识别,字符串会一直延续到文件末尾,PHP 报告 syntax error, unexpected end of file。相反的陷阱是正文中某一行以标识符开头,后面跟着空格或标点,例如 EOT is the marker:它会让字符串提前结束,这一行剩下的部分会被当作 PHP 代码读取(syntax error, unexpected identifier "is")。选一个在文本中永远不会出现在行首的标识符,比如标记语言用 HTML,查询语句用 SQL。

常见问题

PHP 中的 heredoc 是什么?

一种不用引号就能写多行字符串的方式:以 <<<EOT 加换行开头,写下文本,再在单独一行写 EOT; 结束。其中的变量会被替换,和双引号字符串完全一样,而且可以随意使用 " 和 '。

heredoc 和 nowdoc 有什么区别?

heredoc(<<<EOT)会像双引号字符串一样替换变量和转义序列。nowdoc(<<<'EOT',标识符放在单引号里)两者都不处理,每个 $ 和反斜杠都原样保留,就像单引号字符串。

heredoc 的结束标记可以缩进吗?

可以,从 PHP 7.3 开始。结束标记的缩进会从正文的每一行中去掉,所以你可以让 heredoc 跟随代码的缩进。正文的每一行缩进都必须不少于结束标记,否则 PHP 会报解析错误并停止。

怎么在 heredoc 里调用函数?

heredoc 只会插入变量、数组元素、属性和方法调用。可以先调用函数并保存结果,或者把函数名或闭包存到变量里,再在花括号中调用它:$e = 'htmlspecialchars';,然后写 {$e($text)}。

Coddy 编程语言插图

和 Coddy 一起学编程

开始