本文目录导读:

我来详细介绍PHP项目中EDM邮件营销模板的定义、变量使用及最佳实践。
EDM模板基本结构
HTML模板示例
<!-- templates/email/welcome.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">{{subject}}</title>
</head>
<body style="margin:0; padding:0; background-color:#f4f4f4;">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center" style="padding:20px;">
<table width="600" cellpadding="0" cellspacing="0" style="background-color:#ffffff;">
<!-- Header -->
<tr>
<td style="padding:20px; background-color:#3498db; text-align:center;">
<h1 style="color:#ffffff; margin:0;">{{company_name}}</h1>
</td>
</tr>
<!-- Body -->
<tr>
<td style="padding:30px;">
<h2>欢迎您,{{username}}!</h2>
<p>感谢您注册我们的服务。</p>
<p>您的注册邮箱是:{{email}}</p>
<p>注册时间:{{register_time}}</p>
<!-- 按钮 -->
<table cellpadding="0" cellspacing="0" style="margin:20px 0;">
<tr>
<td style="background-color:#3498db; border-radius:25px;">
<a href="{{verify_link}}" style="display:inline-block; padding:12px 30px; color:#ffffff; text-decoration:none; font-size:16px;">
立即验证
</a>
</td>
</tr>
</table>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="padding:20px; background-color:#f8f8f8; text-align:center; font-size:12px; color:#888888;">
<p>{{copyright}}</p>
<p><a href="{{unsubscribe_link}}" style="color:#888888;">取消订阅</a></p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
PHP模板引擎实现
基础模板引擎类
<?php
class EmailTemplate {
private $templates = [];
private $cacheDir = 'cache/templates/';
/**
* 注册模板
*/
public function register($name, $path) {
$this->templates[$name] = $path;
}
/**
* 渲染模板
*/
public function render($templateName, array $variables = []) {
// 获取模板内容
$content = $this->getTemplate($templateName);
// 替换变量
return $this->parseVariables($content, $variables);
}
/**
* 获取模板内容
*/
private function getTemplate($name) {
if (!isset($this->templates[$name])) {
throw new Exception("Template '{$name}' not found");
}
$path = $this->templates[$name];
if (!file_exists($path)) {
throw new Exception("Template file '{$path}' not found");
}
return file_get_contents($path);
}
/**
* 解析变量
*/
private function parseVariables($content, array $variables) {
// 使用双花括号变量替换
foreach ($variables as $key => $value) {
$content = str_replace(
'{{' . $key . '}}',
htmlspecialchars($value, ENT_QUOTES, 'UTF-8'),
$content
);
}
return $content;
}
}
更复杂的模板系统
支持条件和循环的模板系统
<?php
class AdvancedEmailTemplate {
private $blocks = [];
private $sections = [];
/**
* 模板配置
*/
private $config = [
'var_start' => '{{',
'var_end' => '}}',
'block_start' => '{%',
'block_end' => '%}',
'cache_enabled' => true,
'auto_escape' => true
];
/**
* 更强大的模板解析
*/
public function parse($content, $data) {
// 1. 处理条件语句
$content = $this->parseConditionals($content, $data);
// 2. 处理循环语句
$content = $this->parseLoops($content, $data);
// 3. 处理变量
$content = $this->parseVariables($content, $data);
// 4. 处理默认值
$content = $this->parseDefaults($content, $data);
return $content;
}
/**
* 处理条件语句
*/
private function parseConditionals($content, $data) {
return preg_replace_callback(
'/{%\s*if\s+(\w+)\s*%}(.*?){%\s*endif\s*%}/s',
function($matches) use ($data) {
$condition = $matches[1];
$block = $matches[2];
// 检查条件变量是否存在且为真
if (isset($data[$condition]) && $data[$condition]) {
return $block;
}
return '';
},
$content
);
}
/**
* 处理循环语句
*/
private function parseLoops($content, $data) {
return preg_replace_callback(
'/{%\s*loop\s+(\w+)\s+as\s+(\w+)\s*%}(.*?){%\s*endloop\s*%}/s',
function($matches) use ($data) {
$arrayName = $matches[1];
$itemName = $matches[2];
$template = $matches[3];
$result = '';
if (isset($data[$arrayName]) && is_array($data[$arrayName])) {
foreach ($data[$arrayName] as $item) {
$temp = $template;
foreach ($item as $key => $value) {
$temp = str_replace(
'{{' . $itemName . '.' . $key . '}}',
$value,
$temp
);
}
$result .= $temp;
}
}
return $result;
},
$content
);
}
/**
* 处理变量
*/
private function parseVariables($content, $data) {
// 处理简单变量
foreach ($data as $key => $value) {
if (!is_array($value)) {
$search = '{{' . $key . '}}';
$replace = $this->config['auto_escape'] ?
htmlspecialchars($value, ENT_QUOTES, 'UTF-8') : $value;
$content = str_replace($search, $replace, $content);
}
}
return $content;
}
}
使用Twig模板引擎(推荐)
安装
composer require twig/twig
配置和使用
<?php
require_once 'vendor/autoload.php';
class EmailService {
private $twig;
private $mailer;
public function __construct() {
// 配置Twig
$loader = new \Twig\Loader\FilesystemLoader('templates/email/');
$this->twig = new \Twig\Environment($loader, [
'cache' => 'cache/twig/',
'autoescape' => false // EDM模板需要保留HTML
]);
// 添加自定义过滤器
$this->addCustomFilters();
}
/**
* 添加自定义EDM过滤器
*/
private function addCustomFilters() {
// 安全去除HTML标签
$filter = new \Twig\TwigFilter('strip_html', function($string) {
return strip_tags($string);
});
$this->twig->addFilter($filter);
// 截断文本
$filter = new \Twig\TwigFilter('truncate', function($string, $length = 100) {
if (mb_strlen($string) > $length) {
return mb_substr($string, 0, $length) . '...';
}
return $string;
});
$this->twig->addFilter($filter);
}
/**
* 发送营销邮件
*/
public function sendMarketingEmail($to, $template, $data) {
// 渲染模板
$html = $this->twig->render($template, [
'user' => $data['user'],
'products' => $data['products'],
'promotion' => $data['promotion'],
'unsubscribe_url' => $data['unsubscribe_url'],
'tracking_pixel' => $data['tracking_pixel'],
'year' => date('Y'),
'company' => [
'name' => 'Your Company',
'address' => '123 Street, City',
'phone' => '+1 234 567 890'
]
]);
// 发送邮件
// ... 邮件发送代码
}
}
EDM模板变量最佳实践
变量分类管理
<?php
class EDMTemplateVariables {
// 系统变量(自动填充)
public static $systemVariables = [
'unsubscribe_url' => '',
'tracking_pixel' => '',
'current_year' => '',
'campaign_id' => '',
'send_time' => ''
];
// 用户变量
public static $userVariables = [
'username' => '',
'email' => '',
'first_name' => '',
'last_name' => '',
'avatar_url' => '',
'member_since' => '',
'loyalty_points' => 0
];
// 产品变量
public static $productVariables = [
'product_name' => '',
'product_image' => '',
'product_price' => '',
'product_url' => '',
'discount_percentage' => 0,
'original_price' => ''
];
// 内容变量
public static $contentVariables = [
'subject' => '',
'preheader' => '',
'hero_title' => '',
'hero_description' => '',
'cta_text' => '',
'cta_url' => ''
];
}
变量验证和清洗
<?php
class VariableValidator {
/**
* 验证并清洗变量
*/
public static function sanitize($variables, $rules = []) {
$cleaned = [];
foreach ($variables as $key => $value) {
// 检查是否需要特殊处理
if (isset($rules[$key])) {
$cleaned[$key] = self::applyRule($value, $rules[$key]);
} else {
// 默认HTML转义
$cleaned[$key] = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}
}
return $cleaned;
}
/**
* 应用规则
*/
private static function applyRule($value, $rule) {
switch ($rule) {
case 'url':
return filter_var($value, FILTER_VALIDATE_URL) ? $value : '';
case 'email':
return filter_var($value, FILTER_VALIDATE_EMAIL) ? $value : '';
case 'int':
return (int) $value;
case 'float':
return number_format((float) $value, 2);
case 'html':
// 允许部分HTML标签
$allowedTags = '<a><b><strong><i><em><u><br><p><span><div><table><tr><td><img>';
return strip_tags($value, $allowedTags);
default:
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}
}
}
实际应用示例
模板组合使用
<?php
class EDMController {
/**
* 发送营销邮件
*/
public function sendPromotion() {
// 1. 准备数据
$data = [
// 用户信息
'username' => 'John Doe',
'email' => 'john@example.com',
// 促销活动
'promotion' => [
'title' => '夏日大促',
'discount' => '50%',
'code' => 'SUMMER50',
'valid_until' => '2024-08-31'
],
// 推荐产品
'products' => [
[
'name' => '产品1',
'image' => 'https://example.com/product1.jpg',
'price' => '$99.99',
'url' => 'https://example.com/product1'
],
[
'name' => '产品2',
'image' => 'https://example.com/product2.jpg',
'price' => '$149.99',
'url' => 'https://example.com/product2'
]
],
// 系统变量
'unsubscribe_url' => 'https://example.com/unsubscribe?token=xxx',
'tracking_pixel' => 'https://example.com/track?campaign=123',
'current_year' => date('Y')
];
// 2. 变量验证
$validator = new VariableValidator();
$cleanData = $validator->sanitize($data, [
'email' => 'email',
'username' => 'text'
]);
// 3. 渲染模板
$template = new EmailTemplate();
$html = $template->render('promotion', $cleanData);
// 4. 发送邮件
$this->sendEmail($cleanData['email'], $cleanData['username'], $html);
}
}
注意事项
- 安全性:始终对用户输入进行转义
- 响应式:确保模板适配移动设备
- 测试:在不同邮件客户端测试
- 性能:缓存编译后的模板
- 追踪:添加打开率和点击率追踪
这样的EDM模板系统既灵活又安全,可以根据业务需求定制不同的邮件模板。