核心概念:邮件模板如何工作?
Magento 2 的邮件发送流程基于 模板加载器 和 变量解释器。

- 模板加载器:当你触发一个邮件事件(如下单、创建账户等),Magento 会根据预定义的配置加载一个特定的
.html模板文件。 - 变量解释器:模板引擎会扫描这个 HTML 文件,找到所有以 开头和 结尾的“变量占位符”。
- 数据替换:系统会根据当前的上下文(当前订单、当前客户)从相应的数据模型中获取数据,并用这些实际数据替换掉模板中的变量占位符。
变量的类型和常见示例
Magento 2 的邮件变量主要分为以下几类:
全局变量
这些变量在大多数邮件模板中都可用,它们通常与当前作用域有关,比如当前订单、当前客户等。
| 变量代码 | 描述 | 示例 |
|---|---|---|
{{var customer.name}} |
客户的姓名 | John Doe |
{{var customer.email}} |
客户的电子邮件 | john.doe@example.com |
{{var order.increment_id}} |
订单号 | 100000045 |
{{var order.created_at}} |
订单创建日期和时间 | 2025-10-27 10:30:00 |
{{var order.grand_total}} |
订单总金额 | $150.99 |
{{var order.shipping_address.format('html')}} |
格式化的配送地址 HTML | <address>...</address> |
{{var order.billing_address.format('html')}} |
格式化的账单地址 HTML | <address>...</address> |
{{var store.frontend_name}} |
当前商店的名称 | My Awesome Store |
{{var store.url}} |
当前商店的 URL | https://www.myawesomestore.com |
订单相关变量
这些变量专门用于展示订单的详细信息,通常在订单确认、发货等邮件中使用。
| 变量代码 | 描述 | 示例 |
|---|---|---|
{{var order.getShippingDescription()}} |
配送方式名称 | Flat Rate - Fixed |
{{var order.getPaymentMethod().getTitle()}} |
支付方式标题 | Check / Money order |
{{var order.getAllVisibleItems()}} |
订单中所有可见商品的集合 | 一个商品对象列表 |
{{var order.getAllVisibleItems().getSize()}} |
订单中商品的数量 | 3 |
{{var order.getCouponCode()}} |
使用的优惠券代码 | WELCOME10 |
商品相关变量
这些变量需要与订单商品变量结合使用,用于遍历和展示订单中的每一个商品。

在模板中,你通常会使用一个 foreach 循环来遍历商品集合:
{{var order.getAllVisibleItems().each(function(item){})}
<!-- 循环体内的变量使用 item 前缀 -->
<tr>
<td>{{var item.getName()}}</td>
<td>{{var item.getSku()}}</td>
<td>{{var item.getQtyOrdered()}}</td>
<td>{{var item.getPrice()}}</td>
<td>{{var item.getRowTotal()}}</td>
</tr>
{{/var}}
| 变量代码 (在循环内) | 描述 |
|---|---|
{{var item.getName()}} |
商品名称 |
{{var item.getSku()}} |
商品 SKU |
{{var item.getProductUrl()}} |
商品详情页 URL |
{{var item.getQtyOrdered()}} |
已订购数量 |
{{var item.getPrice()}} |
商品单价 |
{{var item.getRowTotal()}} |
该商品行总价 |
{{var item.getImage().toHtml()}} |
商品图片的 HTML <img>
|
自定义变量
这是 Magento 2 最强大的功能之一,你可以为任何数据模型(如客户、产品、订单)添加自定义属性,然后在邮件模板中直接使用它们。
场景示例:假设你在客户注册表单中增加了一个“生日”字段,并希望在新用户欢迎邮件中显示生日祝福。
- 确保数据已保存:确保“生日”字段的数据已经正确保存到
customer_entity数据表中。 - 在模板中使用:
Dear {{var customer.name}}, <br> Welcome to our store! We see that your birthday is on {{var customer.dob}}. Happy Birthday in advance! <br> ...注意:这里的
dob是你数据库中字段名的蛇形命名法表示。
(图片来源网络,侵删)
如何在邮件模板中使用变量
在 HTML 模板文件中直接使用
这是最常见的方式,打开你的邮件模板文件(sales/order/new.html),直接将变量插入到 HTML 代码中。
<!-- 文件: app/design/frontend/Vendor/theme/Magento_Sales/templates/email/order/new.html -->
{{template config_path="email/header"}}
<h1>Your Order #{{var order.increment_id}} Has Been Placed</h1>
<p>Hello {{var customer.name}},</p>
<p>Thank you for your order from {{var store.frontend_name}}. Your order is confirmed and will be processed soon.</p>
<h2>Order Details</h2>
<table>
<thead>
<tr>
<th>Product Name</th>
<th>SKU</th>
<th>Qty</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{{var order.getAllVisibleItems().each(function(item){})}
<tr>
<td>{{var item.getName()}}</td>
<td>{{var item.getSku()}}</td>
<td>{{var item.getQtyOrdered()}}</td>
<td>{{var order.formatPrice(item.getPrice())}}</td> <!-- 使用格式化函数 -->
</tr>
{{/var}}
</tbody>
</table>
<p><strong>Grand Total:</strong> {{var order.formatPrice(order.grand_total)}}</p>
{{template config_path="email/footer"}}
使用 .phtml 文件作为模板
对于更复杂的逻辑,你可以创建一个 .phtml 文件,然后在 HTML 模板中通过 {{block}} 指令来引用它。
-
创建 PHTML 文件:
// 文件: app/code/Vendor/Module/view/frontend/email/order/items.phtml <?php /** @var $block \Vendor\Module\Block\Order\Email\Items */ $items = $block->getOrder()->getAllVisibleItems(); ?> <table> <?php foreach ($items as $item): ?> <tr> <td><?= $block->escapeHtml($item->getName()) ?></td> <td><?= $block->escapeHtml($item->getSku()) ?></td> <!-- 可以在这里写更复杂的 PHP 逻辑 --> </tr> <?php endforeach; ?> </table> -
在 HTML 模板中引用:
<!-- 在你的 new.html 文件中 --> ... <tbody> {{block class='Vendor\Module\Block\Order\Email\Items' area='frontend' order='order' template='Vendor_Module::email/order/items.phtml'}} </tbody> ...
如何查找所有可用的变量
当你不确定某个变量是否存在或如何调用时,可以采用以下方法:
查看核心文件
这是最权威的方法,邮件模板的变量定义通常在模块的 etc/email_templates.xml 文件中。
查看 Magento_Sales 模块的文件:
vendor/magento/module-sales/etc/email_templates.xml
你会看到类似这样的结构:
<template id="sales_order_new" label="New Order" file="order_new.html" type="html">
<variable name="order" required="true">Order</variable>
<variable name="billing" required="true">Order Billing Address</variable>
<variable name="payment_html" required="true">Payment Details</variable>
<variable name="store" required="true">Store</variable>
<variable name="customer" required="true">Customer</variable>
</template>
这个文件定义了 sales_order_new 这个邮件模板有哪些可用的变量(order, billing 等)以及它们对应的数据模型。
使用 var/log/debug.log 日志
在模板中,你可以尝试输出一个对象的类型,以便了解它有哪些方法。
<!-- 在模板中添加这行,然后检查日志 -->
<p>Order object class: {{var order.getClass()}}</p>
<p>Customer object class: {{var customer.getClass()}}</p>
这会输出类似 Magento\Sales\Model\Order 和 Magento\Customer\Model\Customer 的类名,然后你可以去查看这些模型的 PHP 类文件,了解它们有哪些公共方法(即可以在模板中调用的方法)。
使用第三方模块
市面上有一些优秀的开发者工具,如 FireGento_Debug 或 EcomDev_PHPUnit,可以帮助你更直观地查看模板变量。
最佳实践和注意事项
-
始终转义输出:为了防止 XSS 攻击,对于任何可能包含用户输入的变量,都应使用
escapeHtml或escapeUrl等方法。<!-- 安全 --> <td>{{var block.escapeHtml(item.getName())}}</td> <!-- 不安全 --> <td>{{var item.getName()}}</td>注意:在标准的 HTML 模板中,Magento 的模板引擎通常会自动进行基本的转义,但养成手动转义的习惯更安全。
-
使用辅助方法:许多数据模型(如
Order,Store)提供了格式化方法,如formatPrice(),formatDate(),优先使用它们来保证格式的一致性。<!-- 推荐 --> <td>{{var order.formatPrice(item.getPrice())}}</td> <!-- 不推荐 --> <td>$ {{var item.getPrice()}}</td> -
保持模板简洁:如果模板逻辑过于复杂,考虑将其拆分到一个独立的
.phtml文件中,以提高可维护性。 -
测试:在部署到生产环境前,务必在不同的场景下(不同客户、不同订单、不同商品)充分测试你的邮件模板,确保所有变量都按预期显示。
希望这份详细的指南能帮助你更好地理解和使用 Magento 2 的邮件模板变量!
