如何统一监听state_enter.*事件,实现订单邮件收件人覆盖与数据追加?
解决方案:统一处理state_enter事件触发的邮件修改
针对你遇到的问题,无需逐个订阅state_enter.order.state.xxx这类具体事件名称,以下是两种更优方案:
方案1:订阅状态机事件的子类
Shopware中所有state_enter开头的订单相关事件,都会派发对应类型的StateMachineStateChangeEvent子类实例,直接订阅这些类即可覆盖所有相关事件,不用逐个写事件名称:
<?php namespace App\Subscriber; use Shopware\Core\Checkout\Order\Event\OrderStateMachineStateChangeEvent; use Shopware\Core\Checkout\Order\Event\OrderDeliveryStateMachineStateChangeEvent; use Shopware\Core\Checkout\Order\Event\OrderTransactionStateMachineStateChangeEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class StateEnterMailModifierSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents(): array { return [ OrderStateMachineStateChangeEvent::class => 'modifyMailContent', OrderDeliveryStateMachineStateChangeEvent::class => 'modifyMailContent', OrderTransactionStateMachineStateChangeEvent::class => 'modifyMailContent', ]; } public function modifyMailContent($event): void { // 获取对应的实体(订单/配送/交易) $entity = $event->getEntity(); $context = $event->getContext(); // 可将自定义数据存入上下文,后续在邮件发送事件中读取使用 $context->addExtension('custom_order_info', $entity->toArray()); } }
说明:之前你订阅OrderStateMachineStateChangeEvent不生效,大概率是因为只覆盖了订单主状态事件,没包含配送、交易的状态事件,补充对应的子类订阅即可解决。
方案2:直接监听邮件发送前事件(更贴合核心需求)
如果你的核心目标是修改邮件收件人、添加额外数据,无需关心具体触发的state_enter事件,直接监听MailBeforeSentEvent就能统一处理所有流动作发送的邮件:
<?php namespace App\EventListener; use Shopware\Core\Content\MailTemplate\Event\MailBeforeSentEvent; class MailBeforeSendModifierListener { public function __invoke(MailBeforeSentEvent $event): void { $mailStruct = $event->getMailStruct(); $template = $mailStruct->getMailTemplate(); // 筛选状态变更触发的邮件(可根据模板标识调整判断条件) if (str_contains($template->getTechnicalName(), 'order_state') || str_contains($template->getTechnicalName(), 'delivery_state')) { // 覆盖收件人 $mailStruct->setRecipients([ 'custom-recipient@example.com' => '自定义收件人' ]); // 添加额外数据到邮件模板变量 $existingData = $event->getData(); $existingData['custom_extra'] = [ 'note' => '自定义附加内容', 'order_number' => $existingData['order']['orderNumber'] ?? '' ]; $event->setData($existingData); } } }
在config/services.yaml中配置监听器:
services: App\EventListener\MailBeforeSendModifierListener: tags: - { name: kernel.event_listener, event: Shopware\Core\Content\MailTemplate\Event\MailBeforeSentEvent, method: __invoke }
这种方案更直接,后续新增状态无需修改代码,只要是符合条件的邮件发送都会被处理。
关于state_machine.*.state_changed无效的原因
state_machine.*.state_changed是状态变更的通用核心事件,它只负责状态流转的逻辑触发,并不携带邮件收件人等相关信息,因为状态变更和流动作的邮件发送是两个独立环节,所以无法通过它直接修改邮件内容。
内容的提问来源于stack exchange,提问作者Ezycod
相关产品推荐
相关产品推荐

