用 PHP 替换多个占位符?

Posted

技术标签:

【中文标题】用 PHP 替换多个占位符?【英文标题】:Replace multiple placeholders with PHP? 【发布时间】:2012-04-23 18:21:13 【问题描述】:

我有一个发送站点电子邮件的功能(使用 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!";
  

【问题讨论】:

【参考方案1】:

PHP 解决方案可以是:

使用简单的%placeholder% 替换机制: str_replace, strtr, preg_replace 使用纯 PHP 模板和条件逻辑(PHP 中的short open tags 和alternative syntax for control structures)

请找到the wide answer at Programmers.StackExchange 以了解有关PHP 电子邮件模板 的其他方法。

【讨论】:

【参考方案2】:

简单,见strtr­Docs

$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);

【讨论】:

非常感谢,第一段代码向我解释了一切,非常感谢您制作的课程,但我还没有学习 oop,所以会错过它,但第一个示例效果很好我需要这样做谢谢,非常感谢! :) @PHPLover:那也请看a similar email template question and the answers和Efficient way to replace placeholders with variables。【参考方案3】:

你为什么不把电子邮件模板也做成一个 php 文件呢?然后您可以执行以下操作:

Hello <?=$name?>, my name is <?=$your_name?>, today is <?=$date?>

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

在我看来,你的做法很艰难?

【讨论】:

因为它可能会引入代码注入漏洞? BTW 短标签已弃用 如果你用 $y 的值替换 "X",那么它与用 $y 的值替换 $x 的最终结果是一样的——所以没有新的代码注入漏洞? 您假设模板的控制方式与(其余)php 代码相同 @symcbean 短标签未被弃用。它们确实需要在 php.ini 文件中启用 short_open_tags。 PSR-1 编码标准建议只使用 或 = ?>(回显短标签)。 其实因为PHP5.4短标签现在默认开启

以上是关于用 PHP 替换多个占位符?的主要内容,如果未能解决你的问题,请参考以下文章

Java实现JSON{参数}占位符名称替换指定的多个变量值

php 替换“在此处输入标题”占位符文本

php facetwp替换日期选择器占位符文本

试图用实际数据替换占位符文本,但它不起作用

java中有啥方法可以读取占位符的字符串,并且把占位符替换成参数

用动态数据替换占位符