5

概要

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>

PageタグとContent/Containerタグの他に、フロー制御、コレクションの反復処理、動的値の出力などのタグがコアに含まれています。フレームワークは、独自のセットを簡単に追加できるように設計されています。別のプレフィックスと名前空間で登録されたタグ。

PHPへのカスタムタグ

これらのカスタムタグをどのように解析しますか?HTMLファイルが整形式のXMLであるという保証はないため、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。:)

4

3 に答える 3

2

最初の回答とは根本的に異なるため、別の回答を投稿しました。これも価値があるかもしれません。

基本的に、この質問は、正規表現を使用してPHPコードを実行する方法を尋ねています。それほど明白ではないように思われるかもしれませんが、これはevalが達成しようとしていることです。

そうは言っても、preg_replaceのパスを実行してからevalを実行する代わりに、PHPのpreg_replace_callback関数を使用して、一致したときにコードの一部を実行することができます。

関数がどのように機能するかについては、ここを参照してください:http: //us.php.net/manual/en/function.preg-replace-callback.php

于 2010-07-24T19:36:10.313 に答える
2

別のアプローチを提唱させてください。PHPコードを動的に生成し、それを安全に実行する方法を見つけようとするのではなく、タグに遭遇したときに直接実行します。HTMLのブロック全体を1回のパスで処理し、すぐに遭遇した各タグを処理できます。

タグを探すループを作成します。その基本構造は次のようになります。

  1. 位置nにあるカスタムタグを探します。
  2. 位置nの前はすべて単純なHTMLである必要があるため、処理のために保存するか、すぐに出力します($tagsスタックにタグがない場合は、おそらくどこにも保存する必要はありません)。
  3. タグに適切なコードを実行します。を呼び出すコードを生成する代わりに、直接$tags->push呼び出すだけです。$tags->push
  4. 手順1に戻ります。

このアプローチでは、PHP関数を直接呼び出すだけで、PHPコードをその場で作成し、後で実行することはありません。の必要evalはなくなりました。

ステップ3には基本的に2つのケースがあります。オープニングタグに遭遇すると、すぐに実行しますpush。その後、終了タグを押したときに、を実行してpop、適切な方法でタグを処理できます。これで、カスタム要素のコンテンツ全体が処理されました。

この方法でHTMLを処理する方が効率的です。長いHTML文字列で複数の検索と置換を行うことは、各検索と各置換が文字列の長さでO( n )であるため、非効率的です。つまり、文字列を何度も繰り返しスキャンしており、置換を行うたびに、同じ長さのまったく新しい文字列を生成する必要があります。20KBのHTMLがある場合、各置換には、その20KBを検索し、後で新しい20KBの文字列を作成することが含まれます。

于 2010-07-24T19:38:22.963 に答える
0

はい、evalの代わりに、zendやその他の主要なフレームワークが行うことを実行できます。出力バッファリングを使用します。

ob_start();
include($template_file); //has some HTML and output generating PHP
$result = ob_get_contents();
ob_end_clean();
于 2010-07-24T19:15:15.067 に答える