【问题标题】:Help evaluating PHP in .tpl files帮助评估 .tpl 文件中的 PHP
【发布时间】:2011-02-11 02:26:11
【问题描述】:

我使用这个函数来加载模板文件:

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 文件(无论如何都需要我们自己的开发人员访问)

【问题讨论】:

    标签: php template-engine


    【解决方案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}
    

    【讨论】:

    • 但是如何执行循环呢?
    • 已编辑答案以包含 Smarty 的代码示例...尽管您尚未确认您确实在使用它。
    【解决方案2】:

    您可能会接受挑战并为该问题编写一个自定义解析器。

    对于您的问题,更简单、更合适的方法是使用现有的模板引擎,例如 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”。

    【讨论】:

    • 我以前用过 Smarty...我希望能够执行一些基本的 PHP(回显变量和循环),而不需要像 Smarty 这样的复杂应用程序的开销
    • @Webnet 对不起,伙计。您必须设计一个 good 解析器来区分您的 HTML 和 PHP。这复杂的。对于这么简单的需求,你最好使用 Smarty/&lt;insert-template-engine-here&gt;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多