1

そこで、大量の電子メールと変数置換を含むシステムをセットアップしているので、データベースに保存されているテンプレートの変数置換を管理するクラスを作成しています。

簡単な例を次に示します。

// template is stored in db, so that's how this would get loaded in 
$template = "Hello, %customer_name%, thank you for contacting %website_name%"; 
// The array of replacements is built manually and passed to the class 
// with actual values being called from db 
$replacements = array('%customer_name%'=>'Bob', '%website_name%'=>'Acme'); 
$rendered = str_replace(array_keys($replacements), $replacements, $template); 

さて、それはうまく機能し、単一の var 置換、基本的なものに適しています。しかし、for ループが必要な場所がいくつかあり、それを実装する方法がわかりません。

アイデアは、次のようなテンプレートがあることです。

「こんにちは、%customer_name%、{製品} に関する情報をリクエストしていただきありがとうございます」

ここで、{products} はテンプレートに渡される配列であり、次のような形式で、要求された製品に対してループされます。

当社の製品 %product_name% の価格は %product_price% です。%product_url% で詳細をご覧ください。

したがって、これのレンダリングされたバージョンの例は次のようになります。

「こんにちは、ボブ、次の情報をリクエストしていただきありがとうございます。

私たちの製品 WidgetA のコストは $1 です。詳細については、example/A をご覧ください

私たちの製品 WidgetB のコストは 2 ドルです。詳細については、example/B をご覧ください

当社の製品 WidgetC のコストは 3 ドルです。詳細については、example/C を参照してください。

これを達成するための最良の方法は何ですか?

4

2 に答える 2

4

ええと、repalcements/regex を使用するテンプレート エンジンの要点がわかりません。

PHPはすでにテンプレート エンジンです<?php echo $var?><{$var}>{$var}

このように考えてください。PHP はすでにそのエンジンによって変換<?php echo '<b>hello</b>'?><b>hello</b>れているのに、なぜすべてを 2 回繰り返して実行する必要があるのでしょうか。

テンプレートエンジンを実装する方法は次のようになります

まず、テンプレートクラスを作成します

class Template
{
   var $vars = array();

   function __set($key,$val)
   {
      $this->vars[$key] = $val;
   }

   function __get($key)
   {
     return isset($this->vars[$key]) ? $this->vars[$key] : false;
   }

   function output($tpl = false)
   {
      if($tpl === false)
      {
         die('No template file selected in Template::output(...)');
      }

      if(!file_exists(($dir = 'templates/' . $tpl . '.php')))
      {
         die(sprintf('Tpl file does not exists (%s)',$dir));
      }

      new TemplateLoader($dir,$this->vars);
      return true;
   }
}

これは、index.php などのログインで使用するものです。不明な場合は、stdClassと同じようにデータを設定します。出力コマンドを実行すると、データと tpl が下の次のクラスに送信されます。


次に、スタンドアロン クラスを作成して、その中で tpl ファイルをコンパイルします。

class TemplateLoader
{
    private $vars = array();
    private $_vars = array(); //hold vars set within the tpl file
    function __construct($file,$variables)
    {
        $this->vars = $variables;
        //Start the capture;
        ob_start();
           include $file;
           $contents = ob_get_contents();
        ob_end_clean(); //Clean it

       //Return here if you wish
       echo $contents;
    }

    function __get($key)
    {
        return isset($this->vars[$key]) ? $this->vars[$key] : (isset($this->_vars[$key]) ? $this->_vars[$key] : false) : false;
    }

    function __set($key,$val)
    {
       $this->_vars[$key] = $val;
       return true;
    }

   function bold($key)
   {
      return '<strong>' . $this->$key . '</string>';
   }
}

これを個別に保持する理由は、実行するための独自のスペースがあるためです.tplファイルをコンストラクターにインクルードとしてロードするだけなので、一度しかロードできません.ファイルがインクルードされると、すべてのデータにアクセスできます.および TemplateLoader 内のメソッド。


インデックス.php

<?php
   require_once 'includes/Template.php';
   require_once 'includes/TemplateLoader.php';


   $Template = new Template();

   $Template->foo = 'somestring';
   $Template->bar = array('some' => 'array');

   $Template->zed = new stdClass(); // Showing Objects

   $Template->output('index'); // loads templates/index.php
?>

ここで、このページに html を混在させたくありません。なぜなら、php とビュー/テンプレートを分離することで、すべての php が完了していることを確認するためです。html を送信したり、html を使用したりすると、スクリプトの特定の側面が実行されなくなるからです。


テンプレート/index.php

header

    <h1><?php $this->foo;?></h1>
    <ul>
        <?php foreach($this->bar as $this->_foo):?>
            <li><?php echo $this->_foo; ?></li>
        <?php endforeach; ?>
    </ul>
     <p>Testing Objects</p>
     <?php $this->sidebar = $this->foo->show_sidebar ? $this->foo->show_sidebar : false;?>
     <?php if($this->sidebar):?>
        Showing my sidebar.
     <?php endif;?>
footer

ここで、html と php が混在していることがわかりますが、これは問題ありません。これは、Foreach、For などの基本的なものと変数のみを使用する必要があるためです。


注: TemplateLoader クラスでは、次のような関数を追加できます。

function bold($key)
{
   return '<strong>' . $this->$key . '</string>';
}

これにより、テンプレートでのアクションを太字、斜体、atuoloop、css_secure、stripslashs などに増やすことができます。

stripslashes/htmlentites などの通常のツールはすべて使用できます。

太字の小さな例を次に示します。

$this->bold('foo'); //Returns <strong>somestring</string>

inc() などの多くのツールを TempalteLoader クラスに追加して、他の tpl ファイルをロードできます。ヘルパー システムを開発して、$this->helpers->jquery->googleSource

ご不明な点がございましたら、お気軽にお問い合わせください。

----------

データベースに格納する例。

<?php
if(false != ($data = mysql_query('SELECT * FROM tpl_catch where item_name = \'index\' AND item_save_time > '.time() - 3600 .' LIMIT 1 ORDER BY item_save_time DESC')))
{
    if(myslq_num_rows($data) > 0)
    {
       $row = mysql_fetch_assc($data);
       die($row[0]['item_content']);
    }else
    {
       //Compile it with the sample code in first section (index.php)
       //Followed by inserting it into the database
       then print out the content.
    }
}
?>

PHPを含むtplファイルを保存したい場合、それは問題ではありません。tplファイル名を渡すテンプレート内では、ファイルシステムの代わりにdbを検索するだけです

于 2010-07-01T14:53:33.450 に答える
0
$products = array('...');
function parse_products($matches)
{
    global $products;
    $str = '';
    foreach($products as $product) {
       $str .= str_replace('%product_name%', $product, $matches[1]); // $matches[1] is whatever is between {products} and {/products}
    }
    return $str;
}

$str = preg_replace_callback('#\{products}(.*)\{/products}#s', 'parse_products', $str);

アイデアは、{products} と {products} の間の文字列を見つけ、それを何らかの関数に渡し、必要なことは何でも行い、$products 配列を反復処理することです。関数が返すものはすべて、「{products}[anything here]{/products}」全体を置き換えます。

入力文字列は次のようになります。

Requested products: {products}%product_name%{/products}
于 2010-07-01T14:43:43.697 に答える