2012-03-20 3 views
1

記事を格納しているmysqlデータベースを想像してみてください。 ...htmlのphp-codeを使用しています... PHPの

<h1>I'm just foo</h1> 
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p> 
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p> 

とするmysql_queryを使用して、結果を走る表示:

HTMLがそうのように保存されています。

しかし、ここで摩擦があります:たぶん、htmlにマップを挿入するなど、あらかじめ定義された関数を使用したいと思うかもしれません。ユーザーはそれをどのようにHTMLで入力しますか?私は非常によくだけで入力することはできません:そのよう

<?php insertMap() ?> 

は内部のphpタグとPHPタグとしてレンダリングされます。

私は異なったCMSを見てきました。たとえば、{{{insertMap}}}を使用して関数を呼び出します。しかし、どのようにコードを実行し、{{{}}}を探して関数として実行するのですか?

Googleと私はeval()が解決策の一部であると感じていますが(セキュリティ上のリスクはありますが)、提案、ポインタなどは大歓迎です!

答えて

2

基本的には、格納されたコンテンツ内で、そのプレースホルダ(その形式は自由に決めることができる形式)と一致するものを見つけて置換し、それらから派生した式を評価した結果に置き換えます。これにはevalを使用する必要はありません(または良いアイデア)。evalの安全なサブセットのみをサポートする独自のeval-likeコードを非常に簡単に転がすことができます。

プレースホルダテンプレートとして{{{xxx}}}を選択したとします。それに合わせて、最も簡単な方法はregular expressionsからpreg_matchまで、または同じファミリの別の機能を使用することです。置き換えたいので、交換を動的に作成したいので、preg_replace_callbackに行きます。

置き換えるパターンは、中括弧の間の1つ以上の文字と下線のシーケンスに一致する'/{{{([a-zA-Z_]+)}}}/'になります。その中のカッコは正規表現に特有の構文であり、後でその中の部分(「テンプレート」の名前)を中括弧で悩まさずに簡単に参照できるように、それらを使用しました。

コールバックは、パターン与えられた交換用のコンテンツを作成する機能になるだろう:

function produce_replacement($match) { 
    // $match[1] means "the part of the template inside the braces"; 
    // read up on the documentation of preg_replace_callback for more. 
    $producerName = 'evaluate_'.strtolower($match[1]); 
    return function_exists($producerName) ? $producerName() : null; 
} 

この関数は、テンプレート名({{{xxx}}}で例えばxxx)に乗り、機能かどうかを確認するために設計されていますevaluate_xxxが存在します。そうであれば、関数を呼び出して結果を返します。そうでない場合はnullを返します。いずれにしても、元のテキストにテンプレートが置き換えられます。

重要:これは、実装にセキュリティを提供する設計上の決定です!私たちは、ユーザーがテキスト内の任意の "テンプレート"を使用できるようにしましたが、のテンプレートは、evaluate_xxxという名前の関数内にコードが存在する場合に実行されます。これらの関数の有無は、の制御であることを考えれば、ユーザーはマークアップが実際に行うことができるものに制限されています。

だからあなたが今持っていることができます。

$text = "Hello there {{{name}}}!"; 
$pattern = '/{{{([a-zA-Z_]+)}}}/'; 

$text = preg_replace_callback($pattern, 'produce_replacement', $text); 
echo $text; 

function evaluate_name() { 
    return "Joe"; 
} 

​​を。

+0

うわー、それは素晴らしいです!おかげさまで、それを実現しようとします。 – ThomasH

+0

もう一度お悔やみして申し訳ありません。私のニーズに合うようにソリューションを調整しました。実行中の関数に変数を渡すことは難題でした。 .. 私の頭を包み込むことができないのは、おそらく非常にシンプルです:私は{{{showMap}}}、{{{showRating}}}、{{{subItems}}}同じぺージに。 3つのコールがある場合は、最初のコールのみが実行されますが、3回表示されます。 正しい方向で私に指摘する助言はありますか?ありがとう:) – ThomasH

1

これを実行するテンプレートエンジンはたくさんありますが、eval()を使用せずに実行できます。高度な解析クラスを使用します。関数などのリストをあらかじめ定義して使用します。テンプレートエンジンを使用するだけです。

+0

これは5行のコードで実際に行うことができます。テンプレートエンジン、クラスの解析などは必要ありません。 – Jon

+0

フィードバックいただきありがとうございます!テンプレートエンジンで読み上げます。 – ThomasH

+0

@ジョンはい、しかし、私は一般的な答えを1つの関数だけで書いていません。 – safarov

関連する問題