在HEREDOC字符串中调用PHP函数

时间:2008-09-19 18:54:02

标签: php string heredoc

在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风格。这不是一件坏事,但它解释了我的惯性......我想找出让生活变得更轻松的方法,所以我现在正在研究模板。

17 个答案:

答案 0 :(得分:60)

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

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

$my_string = <<<EOT
Number of seconds since the Unix Epoch: {$fn(time())}
EOT;

答案 1 :(得分:52)

我个人不会完全使用HEREDOC。它只是没有一个好的“模板构建”系统。您的所有HTML都被锁定在一个字符串中,该字符串有几个缺点

  • WYSIWYG没有选项
  • IDE中的HTML无代码完成
  • 输出(HTML)锁定到逻辑文件
  • 你最终不得不像你现在想要做的那样使用hack来实现更复杂的模板化,例如循环

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

<强> template_file.php

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

<强>的index.php

<?php

$page_title = "This is a simple demo";

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

include('template_file.php');

答案 2 :(得分:38)

我会做以下事情:

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

不确定你是否认为这更优雅......

答案 3 :(得分: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方法将类方法映射到需要调用的实际函数。

答案 4 :(得分:9)

我有点晚了,但我随机发现了它。对于任何未来的读者,这是我可能会做的:

我只想使用输出缓冲区。基本上,你使用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包含到其缓冲区中,运行任何函数/方法并在此过程中分配任何变量。然后,您只需将缓冲区的内容记录到变量中,然后使用它执行所需的操作。

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

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

答案 5 :(得分:6)

为了完整性,您还可以使用!${''} 黑魔法 parser hack

echo <<<EOT
One month ago was ${!${''} = date('Y-m-d H:i:s', strtotime('-1 month'))}.
EOT;

答案 6 :(得分: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的主要优势。

答案 7 :(得分:5)

在这里找到了包装功能很好的解决方案: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)}";

答案 8 :(得分:5)

此代码段将在userscope中定义具有已定义函数名称的变量,并将它们绑定到包含相同名称的字符串。让我演示一下。

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;

现在可以工作了。

答案 9 :(得分:4)

我会看一下Smarty作为模板引擎 - 我自己没有尝试过任何其他的,但它帮我做得很好。

如果您想坚持使用当前的方法 sans 模板,那么输出缓冲有什么不好?它比你必须声明变量更具灵活性,这些变量是你想要调用的函数的刺激名称。

答案 10 :(得分:2)

有点晚但仍然。 这在heredoc中是可能的!

Have a look in the php manual, section "Complex (curly) syntax"

答案 11 :(得分: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功能,在每个字段名称后添加后缀。这是典型的服务器端任务。

答案 12 :(得分:2)

你忘记了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

答案 13 :(得分:1)

大家应该注意它也适用于双引号字符串。

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

无论如何,

有趣的提示。

答案 14 :(得分:1)

<div><?=<<<heredoc
Use heredoc and functions in ONE statement.
Show lower case ABC="
heredoc
. strtolower('ABC') . <<<heredoc
".  And that is it!
heredoc
?></div>

答案 15 :(得分:0)

<?php
echo <<<ETO
<h1>Hellow ETO</h1>
ETO;
你应该试一试。在结束ETO之后;命令你应该输入。

答案 16 :(得分:0)

今天在php 7.x上更加优雅

<?php

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


echo <<<HEREDOC
this is a test: {$test()}
HEREDOC;