我有一个我创建的电子邮件模板,我希望能够使用[姓名],[电子邮件],[电话]之类的东西,并在发送时替换它们。这些很容易,但我还有其他更复杂的标签,如 [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"不是一种选择。
在这种情况下使用的函数是 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;
这种模式可能看起来有些令人困惑。这里的关键是(?:)?.part。第二个问号表示 '':(''d+) 中的模式是可选的。第一个问号和冒号对字符进行分组,而不捕获它们。它在这里使用,因为我们只需要数组查找的数字。
此正则表达式与 Id 匹配,并应在文本中为您提供 Id:'[([A-Z]*):('d*)']
新的正则表达式'[([A-Z]*:?'d*)']
两者匹配。
这可以使用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);
返回:
您好##名称##,您是否查看了我们的最新产品##product id:32##。我们相信你会喜欢它!如果您不这样做,我们将通过##phone##给您打电话,并将您链接到##article id:12##,这会将您的电子邮件(##email##)放在我们每小时的电子邮件通讯中
在代码板上查看
你可以使用这样的函数:
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);
}
在此处查看工作示例