3

我有一个简单的 Email() 类。它用于从我的网站发送电子邮件。

<?
Email::send($to, $subj, $msg, $options);
?>

我还有一堆用纯 HTML 编写的电子邮件模板,其中包含一些 PHP 变量。例如/inc/email/templates/account_created.php

<p>Dear <?=$name?>,</p>
<p>Thank you for creating an account at <?=$SITE_NAME?>. To login use the link below:</p>
<p><a href="https://<?=$SITE_URL?>/account" target="_blank"><?=$SITE_NAME?>/account</a></p>

为了渲染 PHP 变量,我必须include将模板放入我的函数中。但由于include不返回内容,而是直接将其发送到输出,我不得不用缓冲区函数包装它:

<?
abstract class Email {
    public static function send($to, $subj, $msg, $options = array()) {
        /* ... */
        ob_start();
        include '/inc/email/templates/account_created.php';
        $msg = ob_get_clean();
        /* ... */
    }
}

之后我意识到 PHP vars 没有被渲染,因为它们在函数范围内,所以我必须在模板内全局化变量:

<?
global $SITE_NAME, $SITE_URL, $name;
?>
<p>Dear <?=$name?>,</p>
...

所以问题是是否有更优雅的解决方案?主要是我担心我使用ob_start()and的解决方法global。出于某种原因,这在我看来很奇怪。或者这几乎是常见的做法?

4

3 回答 3

3

一种方法是将文件内容读取到变量中,然后使用正则表达式替换占位符。例如,您有 new-users-template.phtml。您阅读它的内容$content = file_get_content('new-users-templae.phtml');。在这些模板中,您将有占位符,如%%username%%, %%sitename%%, %%siteurl%%. 您需要使用 处理此内容str_replace,替换占位符。将此代码移动到某个"prepareEmailTemplate"函数并将此函数的结果放入您的"send"函数。

于 2012-12-07T16:44:54.563 回答
3

您可以在此答案中找到更优雅的问题解决方案。
注意使用 PHP提取函数来实例化模板变量。
换句话说,您应该将模板解析逻辑移到电子邮件发送功能之外。
例如:

<?php

class SimpleTemplate {
    private $_tpl  = "";
    private $_vars = array();

    function __construct($tpl_name) {
         $this->_tpl = $tpl_name;
    }

    public function __set($name, $value) {
        $this->_vars[$name] = $value;
    }

    public function setVars($values) {
        $this->_vars = $values;
    }

    public function parse() {
        ob_start();
        extract($this->_vars);
        include $this->_tpl;
        return ob_get_clean();
    }
}

abstract class Email {
    public static function send($to, $subj, $msg, $options = array()) {
        /* ... */
    }
}

$tpl = new SimpleTemplate('/inc/email/templates/account_created.php');
$tpl->name = 'Stack Overflow';
$tpl->SITE_NAME = 'site_name';
$tpl->SITE_URL = 'localhost';
Email::send("me@localhost", "Subject", $tpl->parse());

?>
于 2012-12-26T17:49:46.573 回答
0

一种解决方案是将不需要在模板内部而是在函数内部的变量进行全球化send

public static function send($to, $subj, $msg, $options = array()) {
    global $SITE_NAME, $SITE_URL, $name;

    /* ... */
    ob_start();
    include '/inc/email/templates/account_created.php';
    $msg = ob_get_clean();
    /* ... */
}

另一种解决方案是将这些额外的变量作为参数传递。这可能很难看,因为set函数中的参数数量可能会增加很多,具体取决于模板中需要多少参数。为了解决这个问题,实现此解决方案的另一种方法是将这些额外的变量作为哈希传递并即时创建这些变量(使用函数eval)。这是一个例子:

public static function send($to, $extra_vars = array()) {
    foreach ($extra_vars as $key => $value) {
        eval("\$$key = '$value';");
    }

    /* ... */
    ob_start();
    include '/inc/email/templates/account_created.php';
    $msg = ob_get_clean();
    /* ... */
}

那么当你应该像这样调用发送时:

$SITE_NAME = "www.somewebsite.com";
Email::send("recipient", array('SITE_NAME' => $SITE_NAME));
于 2012-12-22T00:31:09.027 回答