帮助评估.tpl文件中的PHP

时间:2011-02-10 17:53:10

标签: php template-engine

我使用此功能加载模板文件:

public function loadTemplate ($replaceToken = array(), $path = 'master.tpl') {
    $template = $this->tru->objectFactory('file', $this->tru->config->get('root.path').'/lib/template/email/'.$path);

    $templateContent = $template->readAll();

    if (count($replaceToken) > 0) {
        foreach ($replaceToken as $token => $value) {
            $templateContent = str_replace('{$'.$token.'}', $value, $templateContent);
        }
    }

    return $templateContent;
}

它允许我调用{$title}之类的变量。现在这已经足够用于非常基本的电子邮件。但现在我已经到了需要使用循环的地步,因此需要能够在这些.tpl文件中运行PHP。我正在努力确定最佳路线,我知道eval()很少是一个很好的解决方案,但这是否是正确的解决方案?

以下是我的一个tpl文件的示例:

            <tr style='border-top: 1px solid rgb(204, 204, 204); border-bottom: 1px solid rgb(204, 204, 204);'>
                <td style='border-color: #ccc; border-style: solid none; border-width: 1px medium; color: #494949 !important; padding: 5px 10px !important; font-size: 12px;'>Description</td>
                <td style='border-color: #ccc; border-style: solid none; border-width: 1px medium; color: #494949 !important; padding: 5px 10px !important; font-size: 12px;'>Vehicle</td>
                <td style='border-color: #ccc; border-style: solid none; border-width: 1px medium; color: #494949 !important; padding: 5px 10px !important; font-size: 12px; text-align: right;'>Unit price</td>
                <td style='border-color: #ccc; border-style: solid none; border-width: 1px medium; color: #494949 !important; padding: 5px 10px !important; font-size: 12px; text-align: right;'>Qty</td>
                <td style='border-color: #ccc; border-style: solid none; border-width: 1px medium; color: #494949 !important; padding: 5px 10px !important; font-size: 12px; text-align: right;'>Amount</td>
            </tr>
            <?
            foreach ($order['productList'] as $product) {
            ?>
            <tr>
                <td style='padding: 10px; border-bottom: 1px <?=$product['border']?> rgb(204, 204, 204); color: #666 !important;'><?=$product['title']?></td>
                <td style='padding: 10px; border-bottom: 1px <?=$product['border']?> rgb(204, 204, 204); color: #666 !important;'><?=$product['vehicle']?></td>
                <td style='padding: 10px; border-bottom: 1px <?=$product['border']?> rgb(204, 204, 204); color: #666 !important; text-align: right;'>$<?=$product['price']?></td>
                <td style='padding: 10px; border-bottom: 1px <?=$product['border']?> rgb(204, 204, 204); color: #666 !important; text-align: right;'><?=$product['quantity']?></td>
                <td style='padding: 10px; border-bottom: 1px <?=$product['border']?> rgb(204, 204, 204); color: #666 !important; text-align: right;'>$<?=$product['lineTotal']?></td>
            </tr>
            <?
            }
            ?>
            <tr>
                <td colspan='3'></td>
                <td style='padding: 2px 5px; text-align: right; font-size: 12px;'>Subtotal</td>
                <td style='padding: 2px 5px; text-align: right; font-size: 12px;'>$<?=$order['subtotal']?></td>
            </tr>

更新

使用eval()这样的安全风险是什么:

public function loadTemplate ($replaceToken = array(), $path = 'master.tpl') {
    $template = $this->tru->objectFactory('file', $this->tru->config->get('root.path').'/lib/template/email/'.$path);

    $templateContent = $template->readAll();

    if (count($replaceToken) > 0) {
        foreach ($replaceToken as $token => $value) {
            $$token = $value;
            $templateContent = str_replace('{$'.$token.'}', $value, $templateContent);
        }
    }

    ob_start();
    eval('?>'.$templateContent.'<?');
    $templateContent = ob_get_contents();
    ob_end_clean();
    return $templateContent;
}

我想不出这可能是不安全的。即使它们包含PHP代码,变量也不是eval()所以我们的.tpl文件(无论如何都需要我们自己的开发人员访问)

2 个答案:

答案 0 :(得分:1)

看起来像Smarty标签。如果是这样,你将PHP包装在{php}标签中。

编辑以添加代码示例:

This is a smarty tag: {$title}

{* this is a smarty foreach loop *}
{forach from=$some_array item=i}
    {$i}
{/foreach}

{php}
// this is literal PHP within a smarty template
foreach ($some_array as $k=>$v) {
   print $k.'=>'.$v.'<br />';
}
{/php}

答案 1 :(得分:0)

您可以接受挑战,并为自己编写一个针对该问题的自定义解析器。

您问题的更简单,更合适的方法是使用现有的模板引擎,如Smarty。有了它,您可以定义执行实际PHP执行的自己的函数(所谓的“块”)或使用预定义的指令({foreach ...})。

使用现有的模板样式会很顺利,因为Smarty会像您的示例中那样评估模板变量:它们表示为{$variable}


修改

我心情不好,输入这个。 eval实际上是一个错字。 a实际上是i。我们走了:

这是实现目标的方法,但不要在生产环境中使用此功能:

$template = '<?php for($i = 0; $i < 10; $i++) { ?>
    <b>something</b><?php
} ?>';

eval('?>' . $template);

这个codepad snippet为你演示了十个“foo”。