PHP - カスタムタグを使用したテンプレート - これはEVALの合法的な使用ですか?
-
29-09-2020 - |
質問
概要
2009年末までに、私はPHP / HTMLのための簡単なテンプレートシステムを、パンフレットウェアタイプのWebサイトの設計者によって社内で使用されます。システムの目的は、PHPによって処理されるカスタムタグを介して、他の方法で純粋なHTMLをテンプレート化できるようにすることです。たとえば、テンプレートページがこのようになります。
<tt:Page template="templates/main.html">
<tt:Content name="leftColumn">
<p> blah blah </p>
...
</tt:Content>
<tt:Content name="rightColumn">
<p> blah blah </p>
...
</tt:Content>
</tt:Page>
.
テンプレート自体がこのようなものに見えるかもしれません:
<html>
<head>...</head>
<body>
<div style="float:left; width:45%">
<tt:Container name="leftColumn" />
</div>
<div style="width:45%">
<tt:Container name="rightColumn" />
</div>
</body>
</html>
.
ページとコンテンツ/コンテナタグの他に、フロー制御のようなもののコアには、コアに含まれている他のタグがいくつかあり、コレクションを介してダイナミックな値などを出力します。別のプレフィックスとネームスペースの下に登録されているタグの独自のセット。
PHPへのカスタムタグ
これらのカスタムタグをどのように解析するのですか? HTMLファイルが正しく形成されていることを保証する以来、XSLT / XPathのようなソリューションは信頼できません。代わりに、登録されたプレフィックスを持つタグを探すために正規表現を使用し、PHPコードを置き換えます。 PHPコードはスタックベースのデザインです...開きタグに遭遇すると、タグを表すオブジェクトがスタックにプッシュされ、その「初期化関数」(もしあれば)が実行されます。登録された閉じるタグが見つかったときはいつでも、最新のオブジェクトがスタックからポップオフされ、その「レンダリング機能」は実行されます。
だから、フレームワークがテンプレートタグをPHPに置き換えた後、私たちの例のページはこのようなものに見えるかもしれません(リアルティでは少し醜い):
<?php $tags->push('tt', 'Page', array('template'=>'templates/main.html')); ?>
<?php $tags->push('tt', 'Content', array('name'=>'leftColumn')); ?>
<p> blah blah </p>
...
<?php $tags->pop(); ?>
<?php $tags->push('tt', 'Content', array('name'=>'rightColumn')); ?>
<p> blah blah </p>
...
<?php $tags->pop(); ?>
<?php $tags->pop(); ?>
.
良い、悪い、そしてeval
今、新しく生成されたPHPコードを実行する方法は?ここでいくつかの選択肢を考えることができます。最も簡単なことは、文字列をeval
、そしてそれが十分に機能することです。しかし、どんなプログラマーもあなたに「Evalは悪である、それを使わないで...」と言うでしょう。そのため、ここで使用できるeval
よりも適切なものはありますか?
php://
の出力ストリームなどを使用して、一時的またはキャッシュファイルを使用していますが、eval
よりも本当の利点を提供しない限り、キャッシングは物事をスピードアップすることができましたが、実際に私たちがこのことについて持っているすべてのサイトはすでに怖くて急速ですので、この時点で速度の最適化をする必要はありません。
質問
このリストの各ものについて:それは良い考えですか?あなたはより良い代替案を考えることができますか?
- 一般的なアイデア全体(HTML / PHPのカスタムタグ)
- 直接処理の代わりにタグをPHPコードに変換する
- スタックベースのアプローチ
-
eval
(または類似)の使用
読書やTIAをあらゆるアドバイスに感謝します。 :)
解決
私は異なるアプローチを支持しましょう。 PHPコードを動的に生成してから、安全に実行する方法を見つけようとしているのではなく、タグが発生するときに直接実行します。 htmlのブロック全体を1パス内にプロセスし、すぐに存在するように各タグを処理できます。
タグを探すループを書き込む。その基本的な構造は次のようになります:
- カスタムタグを探します。 n 。
- 位置の前に n が単純なHTMLである必要があるため、処理または直ちにそれを出力するために保存します(
$tags
スタックにタグがない場合はおそらくどこでも保存する必要はありません。 ) - タグの適切なコードを実行してください。
$tags->push
を呼び出すコードを生成する代わりに、$tags->push
を直接呼び出します。 - 手順1に戻ります。
この方法では、PHP関数を直接呼び出すだけで、その場でPHPコードを作成してから、後で実行することはできません。 eval
の必要性はなくなりました。
基本的にはステップ#3に2つのケースがあります。開封タグが発生したら、即時のpush
を実行します。その後、閉じるタグを押すと、pop
を実行してから適切な方法でタグを処理できます。これで、カスタム要素の内容全体を処理しました。
このようにHTMLを処理することもさらに効率的です。長いHTML文字列に複数の検索と置き換えを行うことは、各検索が文字列の長さのO( n )であるため、非効率的です。繰り返し文字列を繰り返しスキャンしていることを意味します。 20KBのHTMLがある場合は、各交換がその20KBを検索してから、その後新しい20KB文字列を作成します。
他のヒント
私は最初のものとは根本的に異なるので別の答えを投稿しました。
本質的に、この問題は正規表現でPHPコードを実行する方法を求めています。明らかなようには思われるかもしれませんが、これが評価が達成するつもりであるものです。
は、PREG_REPLACEのパスを実行してからEVALを実行する代わりに、PHPのPREG_REAST_CALLBACK関数を使用して一致したときにコードを実行することができます。
関数の機能についてはこちらをご覧ください。 http://us.php.net/manual/en/function.preg-replace-callback.php
はい、evalの代わりに、どのZendおよび他のメジャーフレームワークを実行するかを実行することができます。出力バッファリングを使用します。
ob_start();
include($template_file); //has some HTML and output generating PHP
$result = ob_get_contents();
ob_end_clean();
.