我可以在字符串中添加变量名吗?

时间:2012-11-08 15:10:56

标签: php string variables literals

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

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

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

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

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

由于 彼得

7 个答案:

答案 0 :(得分:7)

如果我理解你的问题,你可以这样做:

客户有textarea或类似信息输入模板

  

亲爱的%NAME%,等等等等%SOMETHING%

然后你可以

$values = array('%SOMETHING%' => $order['something'], '%NAME%' => $order['name']);
$str = str_replace(array_keys($values), array_values($values), $str);

答案 1 :(得分: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']

答案 2 :(得分:1)

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

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

修改:根据评论,Prash答案的变体,

str_replace('%CUSTOMERNAME%', $order['customer_name'], $str);     

答案 3 :(得分:1)

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

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

请注意,它需要在定义$ order的范围内执行。否则(并且最好)使用preg_replace_callback代替最大的灵活性。

您也可以通过这种方式允许其他语法。例如,{order[customer]}%order.customer%比PHP语法更常见且更易于使用。

答案 4 :(得分: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.

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

答案 5 :(得分:0)

您正在寻找的是:

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

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

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

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

答案 6 :(得分:-1)

也许您可以拥有这样的模板:

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

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