You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何统一监听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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 01:37:27