Magento 2扩展订单确认邮件模板添加自定义属性失效问题排查
我太懂这种头疼的感觉了——改核心类明明好使,自己写的模块却掉链子,大概率是重写逻辑或者变量传递的细节没处理到位。我给你梳理几个排查和解决的方向:
1. 先检查重写类的继承与方法逻辑
你的OrderSender类必须正确继承核心类,而且一定要先调用父类的prepareTemplate方法,不然核心模板变量会缺失,自定义属性自然也传不进去。正确的代码结构应该是这样:
<?php namespace ABCSolutions\SalesEmail\Model\Order\Email\Sender; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Email\Sender\OrderSender as CoreOrderSender; class OrderSender extends CoreOrderSender { /** * Prepare email template with variables * * @param Order $order * @return void */ protected function prepareTemplate(Order $order) { // 先执行父类的模板准备逻辑,保证核心变量都初始化完成 parent::prepareTemplate($order); // 这里添加你的自定义属性处理 $customAttrValue = $order->getYourCustomAttributeCode(); // 替换成你的实际属性名 $this->templateContainer->setVariable('custom_attribute', $customAttrValue); } }
很多人重写时容易漏掉parent::prepareTemplate($order)这一步,直接写自己的逻辑,结果导致整个模板变量体系出问题。
2. 确认di.xml的配置位置与正确性
订单邮件属于前端场景,你的di.xml最好放在模块的etc/frontend/目录下(路径:app/code/ABCSolutions/SalesEmail/etc/frontend/di.xml),而不是全局的etc/目录,这样能避免不必要的全局重写冲突。配置内容保持你原来的就行:
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <preference for="Magento\Sales\Model\Order\Email\Sender\OrderSender" type="ABCSolutions\SalesEmail\Model\Order\Email\Sender\OrderSender" /> </config>
3. 验证模板变量的调用是否正确
在你的订单确认邮件模板里,要确保变量名和setVariable里的完全一致,比如模板里应该这么写:
<p>我的自定义属性:{{var custom_attribute}}</p>
如果不确定变量有没有传过来,可以开启Magento的邮件模板调试:
- 后台路径:
Stores > Configuration > Advanced > Developer > Debug - 开启
Template Path Hints for Email和Add Block Names to Hints - 触发一封测试订单邮件,查看邮件里是否能看到
custom_attribute的变量提示,以此确认变量是否传递成功。
4. 必做:清除缓存+重新编译
Magento的重写和配置依赖缓存,执行以下命令更新:
bin/magento cache:clean bin/magento cache:flush bin/magento setup:di:compile
如果是开发者模式,可以跳过setup:di:compile,但缓存清理一定要做。
5. 检查模块是否启用+排查重写冲突
先确认你的模块已经启用:
bin/magento module:status ABCSolutions_SalesEmail
如果未启用,执行:
bin/magento module:enable ABCSolutions_SalesEmail bin/magento setup:upgrade
要是还是不行,可能是有其他模块也重写了OrderSender,导致你的重写被覆盖。用这个命令查看重写优先级:
bin/magento info:di:preference Magento\Sales\Model\Order\Email\Sender\OrderSender
如果输出的不是你的模块,那就是重写冲突了,这时候推荐用**插件(Plugin)**替代重写,更灵活也不容易冲突:
插件替代方案
- 在
etc/frontend/di.xml里配置插件:
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Sales\Model\Order\Email\Sender\OrderSender"> <plugin name="abcsolutions_add_custom_email_attr" type="ABCSolutions\SalesEmail\Plugin\OrderSenderPlugin" sortOrder="10"/> </type> </config>
- 创建插件类
OrderSenderPlugin.php:
<?php namespace ABCSolutions\SalesEmail\Plugin; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Email\Sender\OrderSender; class OrderSenderPlugin { public function afterPrepareTemplate(OrderSender $subject, $result, Order $order) { $customAttrValue = $order->getYourCustomAttributeCode(); $subject->getTemplateContainer()->setVariable('custom_attribute', $customAttrValue); return $result; } }
插件的afterPrepareTemplate方法会在核心方法执行后添加自定义变量,完全避免了重写冲突的问题,也更符合Magento的开发规范。
内容的提问来源于stack exchange,提问作者Bojjaiah

