0

我创建了一个电子邮件模板,我希望能够使用 [NAME]、[EMAIL]、[PHONE] 等内容,并在发送时替换它们。这些很简单,但我还有其他更复杂的标签,如 [PRODUCT:12]、[ARTICLE:23] 等,我想在第一部分中读取“类型”,然后将第二部分作为值处理。

我猜我需要某种 preg_match 然后 preg_replace,但我真的很茫然,因为我不擅长这些功能。

有什么建议么?

- -编辑 - -

只是要清楚。问题在于两部分括号中的 var:value 对。我需要能够看到它是 PRODUCT 并查找返回产品的 id=12 以便我可以建立链接。

---编辑2---

public function parse_message_tags($matches){

    $keys = explode(':', $matches[1]);
    $key = $keys[0];
    $id = (array_key_exists(1, $keys)) ? $keys[1] : -1;
    switch ($key) {
       case 'NAME':
          return $this->session->member->name();
       break;
       case 'FIRST_NAME':
          return $this->session->member->first_name;
       break;
       case 'EMAIL':
          return $this->session->member->email;
       break;
       case 'PRODUCT':
          $product = Product::find_by_id($id);
          return '<a href="/products/'.$product->seo_name.'">'.$product->name.'</a>';
       break;
       case 'ARTICLE':
          $product = Article::find_by_id($id);
          return '<a href="/blog/'.$article->seo_title.'">'.$article->name.'</a>';
       break;
    }

}

public function parse_message($input)
{
    $pattern = '/\[(NAME|FIRST_NAME|EMAIL|PHONE|PRODUCT:\d+|ARTICLE:\d+)\]/';
    return preg_replace_callback($pattern, create_function('$matches', 'return self::parse_message_tags;'), $input);

}

结果:

致命错误:当没有类范围处于活动状态时无法访问 self::

或者

致命错误:不在对象上下文中使用 $this

我猜 create_function() 会将您带出范围/上下文。显然我在这里使用类方法,所以简单地调用“parse_message_tags”不是一种选择。

4

4 回答 4

2

在这种情况下使用的函数是 preg_replace_callback(),因为您需要在索引上执行数组查找第二种类型的标签。在这里将代码包装在一个类中很有用。我们需要以某种方式将数据交给回调函数。使用全局变量会很丑陋。

class EmailTemplate {

    protected $text;
    protected $data;

    public function __construct($text, $data) {
        $this->text = $text;
        $this->data = $data;
    }

    public function callback($matches) {
        $replacement = null;
        $name = $matches[1];
        $index = (int) $matches[2];
        if(isset($this->data[$name])) {
            $value = $this->data[$name];
            if(is_scalar($value)) {
                $replacement = $value;
            } else {
                if(isset($value[$index])) {
                    $replacement = $value[$index];
                }
            }
        }
        return $replacement;
    }

    public function __toString() {
        return preg_replace_callback('/\[(\w+)(?:\:(\d+))?\]/', array($this, 'callback'), $this->text);
    }
}

$data = array(
    "NAME" => "Bob",
    "PRODUCT" => array("dog", "cat", "eggplant")
);
$email = new EmailTemplate("Dear [NAME], please buy my [PRODUCT:2]", $data);

echo $email;

该模式可能看起来有些令人困惑。这里的关键是 (?: )? 部分。第二个问号表示其中的模式 \:(\d+) 是可选的。第一个问号和冒号对字符进行分组而不捕获它们。在这里使用它是因为我们只需要数组查找的数字。

于 2012-08-10T06:43:57.283 回答
1

此正则表达式与 Id 匹配,并应在文本中为您提供 Id:\[([A-Z]*):(\d*)\] 新的正则表达式\[([A-Z]*:?\d*)\]匹配两者。

于 2012-08-10T06:02:14.787 回答
0

你可以使用这样的函数:

function parse_tag($tag) {
  preg_match('#\[(.*?)\]#', $tag, $matches);
  return explode(':', $matches[1]);
}

要将其投入使用,您可能会执行以下操作:

$tests = array(
  '[NAME]' => array('NAME'),
  '[PRODUCT:SHIRT]' => array('PRODUCT', 'SHIRT'), 
  '[ARTICLE:23]' => array('ARTICLE', 23)
);

foreach($tests as $search => $expected) {
  $result = parse_tag($search);
  assert($expected == $result);
}

在此处查看一个工作示例

于 2012-08-10T06:02:30.930 回答
0

这可以使用以下方法相对干净地完成preg_replace_callback()

$pattern = '/\[(NAME|EMAIL|PHONE|PRODUCT:\d+|ARTICLE:\d+)\]/';

function callbackHandler($matches) {
    $keys = explode(':', $matches[1]);
    $key = $keys[0];
    $id = (array_key_exists(1, $keys)) ? $keys[1] : -1;
    switch ($key) {
        case 'NAME':
            return '##name##';
        break;
        case 'EMAIL':
            return '##email##';
        break;
        case 'PHONE':
            return '##phone##';
        break;
        case 'PRODUCT':
            return '##product id:'.$id.'##';
        break;
        case 'ARTICLE':
            return '##article id:'.$id.'##';
        break;
    }
}

$string = "Hello [NAME], have you checked out our latest product [PRODUCT:32]. We're sure you'll like it! If you don't we'll call you on [PHONE] and link you to [ARTICLE:12], which will put your email ([EMAIL]) on our hourly email newsletter";

echo preg_replace_callback($pattern, 'callbackHandler', $string);

回报:

您好##name##,您查看了我们的最新产品##product id:32##。我们相信你会喜欢的!如果您不这样做,我们会在 ##phone## 上给您打电话并将您链接到 ##article id:12##,这会将您的电子邮件 (##email##) 放在我们的每小时电子邮件通讯中

在键盘上查看

于 2012-08-10T07:22:48.680 回答