web-dev-qa-db-ja.com

HEREDOC文字列内でPHP関数を呼び出す

PHPでは、HEREDOC文字列宣言はhtmlのブロックを出力するのに非常に役立ちます。変数に接頭辞$を付けるだけで解析できますが、より複雑な構文($ var [2] [3]など)の場合は、{}括弧内に式を入れる必要があります。

PHP 5、it isでは、実際に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スタイルを逆にする必要があります。それは悪いことではありませんが、それは私の慣性を説明します..生活を楽にする方法を考え出すために、私は今、テンプレートを検討しています。

86
Doug Kavendek

個人的には、これにはHEREDOCをまったく使用しません。それは良い「テンプレート作成」システムにはなりません。すべてのHTMLが文字列でロックされているため、いくつかの欠点があります

  • WYSIWYGのオプションなし
  • IDEからのHTMLのコード補完はありません
  • ロジックファイルにロックされた出力(HTML)
  • ループなどのより複雑なテンプレートを実現するには、今やろうとしているようなハックを使用する必要があります

基本的なテンプレートエンジンを取得するか、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');
52
Peter Bailey

あなたが本当にこれをしたいが、クラスを使用するよりも少し簡単な場合は、使用できます:

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

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

私は次のことをします:

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

これがもっとエレガントだと思うかどうかはわかりません...

39
boxxar

これを試してください(グローバル変数として、または必要なときにインスタンス化されます):

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

  $fn = new Fn();
?>
_

これで、関数呼び出しはすべて_$fn_インスタンスを通過します。したがって、既存の関数testfunction()は、{$fn->testfunction()}を使用してheredocで呼び出すことができます

基本的に、すべての関数をクラスインスタンスにラップし、PHPの___call magic_メソッドを使用して、クラスメソッドを、呼び出す必要がある実際の関数にマップします。

17
Isofarro

私は少し遅れていますが、偶然に出くわしました。将来の読者のために、私がおそらくすることは次のとおりです。

出力バッファーを使用します。基本的に、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をそのバッファーに含め、関数/メソッドを実行し、途中で変数を割り当てます。次に、バッファの内容を変数に記録し、必要な処理を実行します。

そのようにすると、その瞬間にそれをページにエコーしたくない場合は、その必要はありません。出力する前に、ループして文字列に追加し続けることができます。

テンプレートエンジンを使用したくない場合は、これが最善の方法だと思います。

9
BraedenP

完全を期すために、!${''} 黒魔術 パーサーハック

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

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;

残念ながら、質問で関数を変数にバインドすることは良い提案でしたが、最終的にはコードに複雑さを追加しますが、これは価値がなく、コードを読みにくくします。ヒアドキュメントの主な利点。

5
MLU

ここにラッピング機能を備えた素敵なソリューションが見つかりました: 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)}";
5
p.voinov

このスニペットは、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;

動作します。

5

Smarty をテンプレートエンジンとして見てみましょう-私は他のエンジンを試したことはありませんが、うまくいきました。

現在のアプローチsansテンプレートに固執したい場合、出力バッファリングの何がそんなに悪いのでしょうか?呼び出す関数のスティング名である変数を宣言するよりもはるかに柔軟性があります。

4
nickf

@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機能を使用して、各フィールド名の後にサフィックスを追加できます。これは典型的なサーバー側のタスクです。

2
Paulo Buchsbaum

少し遅れましたが、まだです。これは、ヒアドキュメントで可能です!

PHPマニュアルの「Complex(curly)syntax」セクションをご覧ください

2
tftd

あなたはラムダ関数を忘れています:

$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を使用することもできます

2
Ismael Miguel

二重引用符で囲まれた文字列でも機能することに注意してください。

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

とにかく興味深いヒント。

1
SomeOne
<div><?=<<<heredoc
Use heredoc and functions in ONE statement.
Show lower case ABC="
heredoc
. strtolower('ABC') . <<<heredoc
".  And that is it!
heredoc
?></div>
1
Ken
<?php
echo <<<ETO
<h1>Hellow ETO</h1>
ETO;

試してみてください。 ETOの終了後。コマンドを入力してください。

0
Rubel Hossain