用PHP替换多个占位符?

5
我有一个函数,可以发送网站邮件(使用phpmailer),我想做的就是让php用我提供的内容替换email.tpl文件中的所有占位符。对于我来说,问题在于我不想重复编写代码,因此我创建了下面的函数。
如果没有php函数,我将在脚本中执行以下操作:
// email template file
$email_template = "email.tpl";

// Get contact form template from file
$message = file_get_contents($email_template);

// Replace place holders in email template
$message = str_replace("[{USERNAME}]", $username, $message);
$message = str_replace("[{EMAIL}]", $email, $message);

现在我知道如何处理剩下的内容,但是我卡在了str_replace()上面。就像上面所示,我有多个str_replace()函数来替换电子邮件模板中的占位符。我想要的是将str_replace()添加到我的函数(如下),并让它查找我提供的电子邮件模板中所有的[\]实例,并用我提供的占位符值替换它们,如下所示:str_replace("[\]", 'replace_with', $email_body) 问题是我不知道如何将多个占位符及其替换值传递到我的函数中,并让str_replace("[{\}]", 'replace_with', $email_body)处理我给它的所有占位符,并用相应的值替换它们。
因为我想在多个地方使用这个函数,并避免重复的代码,在某些脚本上,我可能会将5个占位符和它们的值传递给函数,另一个脚本可能需要将10个占位符和它们的值传递给函数以在电子邮件模板中使用。
我不确定是否需要在将使用该函数的脚本上使用数组和for循环来使我的php函数从脚本中接收xx占位符和xx值,并循环遍历这些占位符,用它们的值替换它们。
下面是我上面提到的函数。我注释了脚本,这可能更容易解释。
// WILL NEED TO PASS PERHAPS AN ARRAY OF MY PLACEHOLDERS AND THERE VALUES FROM x SCRIPT
// INTO THE FUNCTION ?
function phpmailer($to_email, $email_subject, $email_body, $email_tpl) {

// include php mailer class
require_once("class.phpmailer.php");

// send to email (receipent)
global $to_email;
// add the body for mail
global $email_subject;
// email message body
global $email_body;
// email template
global $email_tpl;

// get email template
$message = file_get_contents($email_tpl);

// replace email template placeholders with content from x script
// FIND ALL INSTANCES OF [{}] IN EMAIL TEMPLATE THAT I FEED THE FUNCTION 
// WITH AND REPLACE IT WITH THERE CORRESPOING VALUES.
// NOT SURE IF I NEED A FOR LOOP HERE PERHAPS TO LOOP THROUGH ALL 
// PLACEHOLDERS I FEED THE FUNCTION WITH AND REPLACE WITH THERE CORRESPONDING VALUES
$email_body       = str_replace("[{\}]", 'replace', $email_body);

// create object of PHPMailer
$mail = new PHPMailer();

// inform class to use smtp
$mail->IsSMTP();
// enable smtp authentication
$mail->SMTPAuth   = SMTP_AUTH;
// host of the smtp server
$mail->Host       = SMTP_HOST;
// port of the smtp server
$mail->Port       = SMTP_PORT;
// smtp user name
$mail->Username   = SMTP_USER;
// smtp user password
$mail->Password   = SMTP_PASS;
// mail charset
$mail->CharSet    = MAIL_CHARSET;

// set from email address
$mail->SetFrom(FROM_EMAIL);
// to address
$mail->AddAddress($to_email);
// email subject
$mail->Subject = $email_subject;
// html message body
$mail->MsgHTML($email_body);
// plain text message body (no html)
$mail->AltBody(strip_tags($email_body));

// finally send the mail
if(!$mail->Send()) {
  echo "Mailer Error: " . $mail->ErrorInfo;
  } else {
  echo "Message sent Successfully!";
  }
}
3个回答

18

简单,见strtr­文档

$vars = array(
    "[{USERNAME}]" => $username,
    "[{EMAIL}]" => $email,
);

$message = strtr($message, $vars);

您可以添加任意多个(或少于)替换对。但是我建议在调用phpmailer函数之前处理模板,以便将事情分开:模板处理和邮件发送:

class MessageTemplateFile
{
    /**
     * @var string
     */
    private $file;
    /**
     * @var string[] varname => string value
     */
    private $vars;

    public function __construct($file, array $vars = array())
    {
        $this->file = (string)$file;
        $this->setVars($vars);
    }

    public function setVars(array $vars)
    {
        $this->vars = $vars;
    }

    public function getTemplateText()
    {
        return file_get_contents($this->file);
    }

    public function __toString()
    {
        return strtr($this->getTemplateText(), $this->getReplacementPairs());
    }

    private function getReplacementPairs()
    {
        $pairs = array();
        foreach ($this->vars as $name => $value)
        {
            $key = sprintf('[{%s}]', strtoupper($name));
            $pairs[$key] = (string)$value;
        }
        return $pairs;
    }
}

使用可以大大简化,然后你可以将整个模板传递给任何需要字符串输入的函数。

$vars = compact('username', 'message');
$message = new MessageTemplateFile('email.tpl', $vars);

非常感谢,第一部分代码让我完全明白了,您制作的类非常感谢,但是我还没有学习面向对象编程,所以会跳过它,但是第一个示例与我需要做的事情非常契合,所以谢谢,非常感谢! :) - PHPLOVER
1
@PHPLover:那么请查看以下类似的电子邮件模板问题及答案(http://stackoverflow.com/q/8176804/367456)和高效替换占位符为变量的方法(https://dev59.com/wlzUa4cB1Zd3GeqP69Jl)。 - hakre

2

0
为什么不把电子邮件模板也做成 PHP 文件呢?这样你就可以像这样做:
Hello <?=$name?>, my name is <?=$your_name?>, today is <?=$date?>

在电子邮件中生成您的HTML,然后将结果作为电子邮件发送。

对我来说,你似乎走了一条艰难的路?


因为它可能会引入代码注入漏洞?顺便说一下,短标签已经被弃用了。 - symcbean
如果您将“X”替换为$y的值,则与将$x替换为$y的值具有相同的净结果,因此不存在新的代码注入漏洞? - Laurence
你假设模板的控制方式与(其余)PHP代码相同。 - symcbean
@symcbean 短标签并未被弃用。但是在 php.ini 文件中需要启用 short_open_tags。PSR-1 编码规范建议只使用 <?php ?> 或 <?= ?>(echo 短标签)。 - Brainfeeder
实际上,自PHP5.4以来,短标签现在默认已启用。 - Laurence

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接