更新 -すべての応答に感謝します。このQはややこしくなってきているので、誰かが興味を持っているなら続編を始めました.
私は友人のために簡単なスクリプトをまとめていましたが、PHP でテンプレートを作成するための非常に簡単な方法を見つけました。
基本的には、HTML ドキュメントをヒアドキュメント文字列として解析することを目的としているため、その中の変数は PHP によって展開されます。
パススルー関数を使用すると、式の評価と、文字列内の関数および静的メソッドの呼び出しが可能になります。
function passthrough($s){return $s;}
$_="passthrough";
ヒアドキュメント文字列内のドキュメントを解析するコードは、とてつもなく単純です。
$t=file_get_contents('my_template.html');
eval("\$r=<<<_END_OF_FILE_\n$t\_END_OF_FILE_;\n");
echo $r;
唯一の問題は、それが使用することeval
です。
質問
eval
を使用せずに、パーサーや大量の正規表現の狂気を追加せずに、この種のテンプレートを作成する方法を考えられる人はいますか?完全なパーサーを作成せずに、PHP 変数に属さない迷子のドル記号をエスケープするための提案はありますか? 漂遊ドル記号の問題により、このアプローチは「真剣に」使用できなくなりますか?
テンプレート化された HTML コードのサンプルを次に示します。
<script>var _lang = {$_(json_encode($lang))};</script>
<script src='/blah.js'></script>
<link href='/blah.css' type='text/css' rel='stylesheet'>
<form class="inquiry" method="post" action="process.php" onsubmit="return validate(this)">
<div class="filter">
<h2>
{$lang['T_FILTER_TITLE']}
</h2>
<a href='#{$lang['T_FILTER_ALL']}' onclick='applyFilter();'>
{$lang['T_FILTER_ALL']}
</a>
{$filter_html}
</div>
<table class="inventory" id="inventory_table">
{$table_rows}
<tr class="static"><th colspan="{$_($cols+1)}">
{$lang['T_FORM_HELP']}
</th></tr>
{$form_fields}
<tr class="static">
<td id="validation" class="send" colspan="{$cols}"> </td>
<td colspan="1" class="send"><input type="submit" value="{$lang['T_SEND']}" /></td>
</tr>
</table>
</form>
テンプレートを使用する理由
PHP でテンプレート レイヤーを作成する必要があるかどうかについては、いくつかの議論がありましたが、確かに、PHP は既にテンプレート作成に優れています。
テンプレートが役立ついくつかの簡単な理由:
あなたはそれを制御することができます
インタープリターに渡す前にファイルを前処理すると、ファイルをより細かく制御できます。何かを挿入したり、パーミッションをロックダウンしたり、悪意のある php / javascript をスクレイピングしたり、キャッシュしたり、xsl テンプレートを介して実行したりできます。
優れた MVC 設計
テンプレート化により、モデルとコントローラーからのビューの分離が促進されます。
ビュー内のタグにジャンプしたり、
<?php ?>
タグからジャンプしたりすると、怠惰になり、データベース クエリを実行したり、他のサーバー アクションを実行したりしやすくなります。上記のような方法を使用すると、「ブロック」(セミコロンなし) ごとに 1 つのステートメントしか使用できないため、そのトラップに引っかかるのははるかに困難です。<?= ... ?>
ほとんど同じ利点がありますが...短いタグが常に有効になっているわけではありません
...そして、アプリをさまざまな構成で実行したいと考えています。
私が最初にコンセプトを一緒にハックするとき、それは 1 つの php ファイルとして始まります。<?php
しかし、それが大きくなる前に、すべてのphpファイルの最初と?>
最後に1つだけがあり、できればすべてがコントローラー、設定、画像サーバーなどを除くクラスである場合を除き、満足できません.
ビューにあまり PHP を入れたくないのは、デザイナーが混乱するからです。
<a href="<?php $img="$img_server/$row['pic'].png"; echo $img; ?>">
<img src="<?php echo $img; ?>" /></a>
これは、プログラマーが見るには十分に困難です。平均的なグラフィック デザイナーは、それに近づくことはできません。このようなものは、対処がはるかに簡単です。
<a href="{$img}"><img src="{$img}" /></a>
プログラマーは厄介なコードを html から除外したので、デザイナーはデザインの魔法を働かせることができます。わーい!
クイックアップデート
みんなのアドバイスを考慮して、ファイルを前処理するのが最善だと思います。中間ファイルは、テンプレートをシンタックス シュガーにして、通常の "php テンプレート" にできるだけ近づける必要があります。私がそれで遊んでいる間、今のところ評価はまだ残っています。ヒアドキュメントは、その役割を少し変更しました。後で詳しく書いて、いくつかの回答に返信しようとしますが、今のところ...
<?php
class HereTemplate {
static $loops;
public function __construct () {
$loops=array();
}
public function passthrough ($v) { return $v; }
public function parse_markup ($markup, $no_escape=null, $vars=array()) {
extract($vars);
$eot='_EOT_'.rand(1,999999).'_EOT_';
$do='passthrough';
if (!$no_escape) $markup=preg_replace(
array(
'#{?{each.*(\$\w*).*(\$\w*).*(\$\w*).*}}?#',
'#{?{each.*(\$\w*).*(\$\w*).*}}?#',
'#{?{each}}?#',
'#{{#', '#}}#',
'#{_#', '#_}#',
),
array(
"<?php foreach (\\1 as \\2=>\\3) { ?>",
"<?php foreach (\\1 as \\2) { ?>",
"<?php } ?>",
"<?php echo <<<$eot\n{\$this->passthrough(", ")}\n$eot\n ?>",
"<?php ", " ?>",
),
$markup);
ob_start();
eval(" ?>$markup<?php ");
echo $markup;
return ob_get_clean();
}
public function parse_file ($file) {
// include $file;
return $this->parse_markup(file_get_contents($file));
}
}
// test stuff
$ht = new HereTemplate();
echo $ht->parse_file($argv[1]);
?>
...
<html>
{{each $_SERVER $key $value}
<div id="{{$key}}">
{{!print_r($value)}}
</div>
{each}}
</html>