帮助评估 .tpl 文件中的 PHP
我使用此函数来加载模板文件:
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>
update
像这样使用 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 文件(无论如何都需要我们自己的开发人员访问权限)
I use this function to load template files:
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('{
It allows me to call variables such as {$title}
. This has been sufficient for now with very basic emails. But now I'm getting to the point where I need to use loops and thus need to be able to run PHP in these .tpl files. I'm struggling to determine the best route, I know eval() is rarely a good solution, but is it he right solution here?
Here's an example of one of my tpl files:
<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;'>lt;?=$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;'>lt;?=$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;'>lt;?=$order['subtotal']?></td>
</tr>
update
What are the security risks with using eval()
like this:
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('{
I can't think of how this could be insecure. The variables even if they contain PHP code aren't being eval()'d so our .tpl files (which require our own developer access anyways)
.$token.'}', $value, $templateContent);
}
}
return $templateContent;
}
It allows me to call variables such as {$title}
. This has been sufficient for now with very basic emails. But now I'm getting to the point where I need to use loops and thus need to be able to run PHP in these .tpl files. I'm struggling to determine the best route, I know eval() is rarely a good solution, but is it he right solution here?
Here's an example of one of my tpl files:
update
What are the security risks with using eval()
like this:
I can't think of how this could be insecure. The variables even if they contain PHP code aren't being eval()'d so our .tpl files (which require our own developer access anyways)
.$token.'}', $value, $templateContent);
}
}
ob_start();
eval('?>'.$templateContent.'<?');
$templateContent = ob_get_contents();
ob_end_clean();
return $templateContent;
}
I can't think of how this could be insecure. The variables even if they contain PHP code aren't being eval()'d so our .tpl files (which require our own developer access anyways)
.$token.'}', $value, $templateContent); } } return $templateContent; }It allows me to call variables such as {$title}
. This has been sufficient for now with very basic emails. But now I'm getting to the point where I need to use loops and thus need to be able to run PHP in these .tpl files. I'm struggling to determine the best route, I know eval() is rarely a good solution, but is it he right solution here?
Here's an example of one of my tpl files:
update
What are the security risks with using eval()
like this:
I can't think of how this could be insecure. The variables even if they contain PHP code aren't being eval()'d so our .tpl files (which require our own developer access anyways)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这看起来像一个 Smarty 标签。如果是这样,请将 PHP 包装在 {php} 标记中。
编辑以添加代码示例:
That looks like a Smarty tag. If so, you wrap PHP in a {php} tag.
Edit to add code sample:
您可能会接受挑战并为该问题自己编写一个自定义解析器。
解决您的问题更简单、更合适的方法是使用现有的模板引擎,例如 Smarty。有了它,您可以定义自己的函数(所谓的“块”)来执行实际的 PHP 执行,也可以使用预定义的指令 (
{foreach ...}
)。它会非常适合您现有的模板样式,因为 Smarty 会像您的示例中那样评估模板变量:它们表示为
{$variable}
。编辑
我感觉很糟糕,打字这个。
eval
实际上是一个拼写错误。a
实际上是一个i
。我们开始吧:这是实现您目标的一种方法,但请不要在生产环境中使用它:
这个键盘片段 为您演示了十个“foo”。
You might take the challenge and write yourself a custom parser for that problem.
The easier and more fitting way for your question would be to use already existing templating engines like Smarty. With it, you can either define own functions (so-called "blocks") that do the actual PHP execution or use pre-defined directives (
{foreach ...}
).It'll go pretty smooth with your existing template style, since Smarty evaluates template variables like in your example: they're expressed as
{$variable}
.EDIT
I feel bad, typing this.
eval
is actually a typo. Thea
is actually ani
. Here we go:This is a way to accomplish your goal but please do not use this in a production environment:
This codepad snippet gives you a demonstration of ten "foo"s.