1

我正在创建一个 OpenCart 扩展,管理员可以在其中使用管理面板中的用户界面更改他的电子邮件模板。

我希望用户可以选择将变量添加到他的自定义电子邮件模板中。例如,他可以输入:

您好$order['customer_firstname'],您的订单已处理完毕。

此时 $order 将是未定义的,用户只是告诉定义要发送的消息。这将被存储到数据库中,并在发送电子邮件时调用。

问题是,我如何让“ $order['customer_firstname']”变成文字字符串,然后在必要时转换为变量?

谢谢彼得

4

7 回答 7

7

如果我正确理解您的问题,您可以执行以下操作:

客户有textarea或类似的输入模板

亲爱的 %NAME%,胡说八道 %SOMETHING%

那么你可以有

$values = array('%SOMETHING%' => $order['something'], '%NAME%' => $order['name']);
$str = str_replace(array_keys($values), array_values($values), $str);
于 2012-11-08T15:13:07.603 回答
2

用户将使用大约 40 个变量。有没有办法可以为每个“%VARIABLE%”设置它?

是的,您可以借助回调函数轻松地为每个变量执行此操作。

这允许您使用您选择的函数处理每个匹配,返回所需的替换。

$processed = preg_replace_callback("/%(\S+)%/", function($matches) {
        $name = $matches[1]; // between the % signs
        $replacement = get_replacement_if_valid($name);
        return $replacement;
    },
    $text_to_replace_in
);

从这里,你可以做任何你喜欢的事情,点符号,例如:

function get_replacement_if_valid($name) {
    list($var, $key) = explode(".", $name);
    if ($var === "order") {
        $order = init_oder(); // symbolic
        if(array_key_exists($key, $order)) {
            return $order[$key];
        }
     }
     return "<invalid key: $name>";
}

这种简单的实现允许您处理替换,例如%order.name%$order['name'].

于 2012-11-08T15:23:19.650 回答
1

您可以将其存储为Hello $order['customer_firstname']并在访问时确保您有双引号"" 以将变量转换为其相应的值。

  echo "Hello $order['customer_firstname']"; 

编辑:根据评论,Prash 回答的一个变体,

str_replace('%CUSTOMERNAME%', $order['customer_name'], $str);     
于 2012-11-08T15:14:16.650 回答
1

如果您想保留 PHP 语法,那么正则表达式将适合过滤它们:

$text = preg_replace(
            "/   [$] (\w+)  \[ '? (\w+) \'? \]   /exi",
            "$$1['$2']",    # basically a constrained eval
            $text
        );

请注意,它需要在与 $order 定义相同的范围内执行。其他(最好)使用preg_replace_callback来获得最大的灵活性。

您也可以通过这种方式允许另一种语法。例如{order[customer]}or%order.customer%比 PHP 语法更常见并且可能更容易使用。

于 2012-11-08T15:18:56.567 回答
1

您可以定义自己的简单模板引擎:

function template($text, $context) {
    $tags = preg_match_all('~%([a-zA-Z0-9]+)\.([a-zA-Z0-9]+)%~', $text, $matches);

    for($i = 0; $i < count($matches[0]); $i++) {
        $subject = $matches[0][$i];
        $ctx = $matches[1][$i];
        $key = $matches[3][$i];
        $value = $context[$ctx][$key];

        $text = str_replace($subject, $value, $text);
    }

    return $text;
}

这使您可以像这样转换字符串:

$text = 'Hello %order.name%. You have %order.percent%% discount. Pay a total ammount of %payment.ammount% using %payment.type%.';

$templated = template($text, array(
    'order' => array(
        'name' => 'Alex',
        'percent' => 20
    ),

    'payment' => array(
        'type' => 'VISA',
        'ammount' => '$299.9'
    )
));
echo $templated;

进入这个:

Hello Alex. You have 20% discount. Pay a total ammount of $299.9 using VISA.

这允许您定义任意数量的变量。

于 2012-11-08T15:21:15.157 回答
0

您正在寻找的是:

eval("echo \"" . $input . "\";");

但是请不要那样做,因为这样可以让用户运行他想要的任何代码。

更好的方法是自定义模板系统,您可以在其中提供可用值列表供用户使用%user_firstname%. 然后,您可以使用str_replace和朋友将这些标签与实际值交换出来,但您仍然可以扫描任何类型的恶意代码。

这就是为什么 Markdown 和类似的东西很受欢迎的原因;它们使用户可以控制其内容的呈现,同时仍然可以轻松扫描 HTML/JS/PHP/SQL 注入/他们可能试图潜入的任何其他内容,因为白名单比黑名单更容易。

于 2012-11-08T15:20:16.470 回答
-1

也许你可以有一个这样的模板:

$tpl = "Hello {$order['customer_firstname']}, your order has been processed.".

如果 $order 并且该特定键不为空,则可以echo $tpl直接使用并在文本中显示'customer_firstname'键的内容。关键是这里的花括号。

于 2012-11-08T15:23:18.153 回答