99

在 PHP 中,HEREDOC 字符串声明对于输出 html 块非常有用。您可以通过在变量前加上 $ 来解析变量,但对于更复杂的语法(如 $var[2][3]),您必须将表达式放在 {} 大括号内。

在 PHP 5 中,实际上可以在 HEREDOC 字符串内的 {} 大括号内进行函数调用,但您必须做一些工作。函数名本身必须存储在一个变量中,并且您必须像调用它是动态命名的函数一样调用它。例如:

$fn = 'testfunction';
function testfunction() { return 'ok'; }
$string = <<< heredoc
plain text and now a function: {$fn()}
heredoc;

如您所见,这比仅仅更混乱一点:

$string = <<< heredoc
plain text and now a function: {testfunction()}
heredoc;

除了第一个代码示例之外,还有其他方法,例如突破 HEREDOC 来调用函数,或者扭转问题并执行以下操作:

?>
<!-- directly output html and only breaking into php for the function -->
plain text and now a function: <?PHP print testfunction(); ?>

后者的缺点是输出直接放入输出流(除非我使用输出缓冲),这可能不是我想要的。

所以,我的问题的本质是:有没有更优雅的方法来解决这个问题?

根据回复进行编辑:看起来某种模板引擎确实会让我的生活更轻松,但它需要我基本上颠倒我通常的 PHP 风格。并不是说那是一件坏事,但它解释了我的惰性。不过,我正在想办法让生活更轻松,所以我现在正在研究模板。

4

17 回答 17

76

如果您真的想这样做但比使用类更简单,您可以使用:

function fn($data) {
  return $data;
}
$fn = 'fn';

$my_string = <<<EOT
Number of seconds since the Unix Epoch: {$fn(time())}
EOT;
于 2012-05-23T04:06:59.510 回答
53

就个人而言,我根本不会为此使用HEREDOC。它只是不构成一个好的“模板构建”系统。您所有的 HTML 都被锁定在一个有几个缺点的字符串中

  • 所见即所得没有选项
  • IDE 中的 HTML 没有代码完成
  • 输出 (HTML) 锁定到逻辑文件
  • 您最终不得不使用像您现在尝试做的那样的技巧来实现更复杂的模板,例如循环

获取一个基本的模板引擎,或者只使用 PHP 和包含 - 这就是语言有<?php?>分隔符的原因。

模板文件.php

<html>
<head>
  <title><?php echo $page_title; ?></title>
</head>
<body>
  <?php echo getPageContent(); ?>
</body>

索引.php

<?php

$page_title = "This is a simple demo";

function getPageContent() {
    return '<p>Hello World!</p>';
}

include('template_file.php');
于 2008-09-19T19:10:54.043 回答
45

我会做以下事情:

$string = <<< heredoc
plain text and now a function: %s
heredoc;
$string = sprintf($string, testfunction());

不知道你是否认为这更优雅......

于 2008-09-19T18:59:53.973 回答
17

试试这个(或者作为全局变量,或者在需要时实例化):

<?php
  class Fn {
    public function __call($name, $args) {
      if (function_exists($name)) {
        return call_user_func_array($name, $args);
      }
    }
  }

  $fn = new Fn();
?>

现在任何函数调用都通过$fn实例。所以现有的函数testfunction()可以在heredoc中调用{$fn->testfunction()}

基本上我们将所有函数包装到一个类实例中,并使用 PHP 的__call magic方法将类方法映射到需要调用的实际函数。

于 2009-12-22T18:11:55.970 回答
17

为了完整起见,您还可以使用!${''} black magic parser hack

echo <<<EOT
One month ago was ${!${''} = date('Y-m-d H:i:s', strtotime('-1 month'))}.
EOT;
于 2016-03-24T14:31:31.647 回答
10

我有点晚了,但我偶然发现了它。对于任何未来的读者,这就是我可能会做的事情:

我只会使用输出缓冲区。所以基本上,你使用 ob_start() 开始缓冲,然后在其中包含任何函数、变量等的“模板文件”,获取缓冲区的内容并将它们写入字符串,然后关闭缓冲区。然后,您使用了所需的任何变量,可以运行任何函数,并且您的 IDE 中仍然可以使用 HTML 语法突出显示。

这就是我的意思:

模板文件:

<?php echo "plain text and now a function: " . testfunction(); ?>

脚本:

<?php
ob_start();
include "template_file.php";
$output_string = ob_get_contents();
ob_end_clean();
echo $output_string;
?>

因此脚本将 template_file.php 包含在其缓冲区中,运行任何函数/方法并在此过程中分配任何变量。然后你只需将缓冲区的内容记录到一个变量中,然后用它做你想做的事。

这样,如果您不想在那一秒将其回显到页面上,则不必这样做。您可以在输出之前循环并继续添加到字符串。

如果您不想使用模板引擎,我认为这是最好的方法。

于 2009-09-06T20:49:04.003 回答
7

在这里找到了带有包装功能的好解决方案:http: //blog.nazdrave.net/ ?p=626

function heredoc($param) {
    // just return whatever has been passed to us
    return $param;
}

$heredoc = 'heredoc';

$string = <<<HEREDOC
\$heredoc is now a generic function that can be used in all sorts of ways:
Output the result of a function: {$heredoc(date('r'))}
Output the value of a constant: {$heredoc(__FILE__)}
Static methods work just as well: {$heredoc(MyClass::getSomething())}
2 + 2 equals {$heredoc(2+2)}
HEREDOC;

// The same works not only with HEREDOC strings,
// but with double-quoted strings as well:
$string = "{$heredoc(2+2)}";
于 2014-11-20T20:53:01.183 回答
6

此代码段将使用您在用户范围内定义的函数的名称定义变量,并将它们绑定到包含相同名称的字符串。让我演示一下。

function add ($int) { return $int + 1; }
$f=get_defined_functions();foreach($f[user]as$v){$$v=$v;}

$string = <<< heredoc
plain text and now a function: {$add(1)}
heredoc;

现在可以工作了。

于 2010-12-08T13:02:34.787 回答
5

我认为使用 heredoc 非常适合生成 HTML 代码。例如,我发现以下内容几乎完全不可读。

<html>
<head>
  <title><?php echo $page_title; ?></title>
</head>
<body>
  <?php echo getPageContent(); ?>
</body>

但是,为了实现简单性,您必须在开始之前评估功能。我不认为这是一个如此可怕的约束,因为这样做,您最终会将计算与显示分开,这通常是一个好主意。

我认为以下内容非常易读:

$page_content = getPageContent();

print <<<END
<html>
<head>
  <title>$page_title</title>
</head>
<body>
$page_content
</body>
END;

不幸的是,即使您在问题中提出了将函数绑定到变量的一个很好的建议,但最终,它给代码增加了一定程度的复杂性,这是不值得的,并且使代码的可读性降低,这是heredoc 的主要优势。

于 2011-06-17T10:54:50.923 回答
4

我会把Smarty看成一个模板引擎——我自己没有尝试过任何其他的,但它做得很好。

如果您想坚持当前的模板方法,那么输出缓冲有什么不好呢?与必须声明作为您要调用的函数的字符串名称的变量相比,它会给您更大的灵活性。

于 2008-09-19T23:42:49.287 回答
3

你忘记了 lambda 函数:

$or=function($c,$t,$f){return$c?$t:$f;};
echo <<<TRUEFALSE
    The best color ever is {$or(rand(0,1),'green','black')}
TRUEFALSE;

您也可以使用函数 create_function

于 2013-09-23T09:02:49.053 回答
2

有点晚了,但还是。这在heredoc中是可能的!

查看 php 手册的“复杂(卷曲)语法”部分

于 2011-04-08T22:58:01.283 回答
2

这是一个使用@CJDennis 提议的好例子:

function double($i)
{ return $i*2; }

function triple($i)
{ return $i*3;}

$tab = 'double';
echo "{$tab(5)} is $tab 5<br>";

$tab = 'triple';
echo "{$tab(5)} is $tab 5<br>";

例如,HEREDOC 语法的一个很好的用途是在数据库中生成具有主从关系的巨大表单。可以在 FOR 控件中使用 HEREDOC 功能,在每个字段名称后添加一个后缀。这是一个典型的服务器端任务。

于 2013-01-18T04:24:58.050 回答
2

今天在 php 7.x 上更优雅一点

<?php

$test = function(){
    return 'it works!';
};


echo <<<HEREDOC
this is a test: {$test()}
HEREDOC;
于 2019-11-20T23:09:12.800 回答
1

伙计们应该注意,它也适用于双引号字符串。

http://www.php.net/manual/en/language.types.string.php

无论如何,有趣的提示。

于 2010-05-10T11:20:13.147 回答
1
<div><?=<<<heredoc
Use heredoc and functions in ONE statement.
Show lower case ABC="
heredoc
. strtolower('ABC') . <<<heredoc
".  And that is it!
heredoc
?></div>
于 2016-09-17T02:13:18.330 回答
0
<?php
echo <<<ETO
<h1>Hellow ETO</h1>
ETO;

你应该试试看 。ETO结束后;命令你应该回车。

于 2016-09-03T05:36:49.717 回答