我使用此功能加载模板文件:
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文件(无论如何都需要我们自己的开发人员访问)
答案 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”。