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

Shopware:如何在OrderWrittenEvent中获取SalesChannelContext以发送邮件?

解决OrderWrittenEvent中获取SalesChannelContext的问题

在OrderWrittenEvent中无法直接拿到SalesChannelContext是正常的,你不需要调用Store API来获取——Shopware提供了内置服务来创建合法的SalesChannelContext实例,具体步骤如下:

1. 从订单实体中提取必要ID

首先从OrderWrittenEvent的订单数据里取出创建上下文所需的核心参数:

public function onOrderWritten(OrderWrittenEvent $event): void
{
    foreach ($event->getWriteResults() as $writeResult) {
        // 过滤非更新操作或非订单实体的情况
        if (!$writeResult->getEntity() instanceof OrderEntity || $writeResult->getOperation() !== WriteResult::OPERATION_UPDATE) {
            continue;
        }
        
        /** @var OrderEntity $order */
        $order = $writeResult->getEntity();
        $salesChannelId = $order->getSalesChannelId();
        $customerId = $order->getCustomerId();
        $languageId = $order->getLanguageId();
        $currencyId = $order->getCurrencyId();
        
        // 执行你的自定义条件判断,比如检查API响应错误标记
        if (!$this->shouldSendMail($order)) {
            continue;
        }
        
        // 后续创建上下文并发送邮件
    }
}

2. 注入SalesChannelContextFactory服务

在事件订阅类的构造函数中,注入Shopware官方的SalesChannelContextFactoryInterface——这是创建SalesChannelContext的标准方式:

use Shopware\Core\System\SalesChannel\Context\SalesChannelContextFactoryInterface;
use Shopware\Core\Framework\Event\EventSubscriberInterface;

class OrderWrittenSubscriber implements EventSubscriberInterface
{
    private $salesChannelContextFactory;
    private $emailService;

    public function __construct(
        SalesChannelContextFactoryInterface $salesChannelContextFactory,
        \Swag\BasicExample\Service\EmailService $emailService
    ) {
        $this->salesChannelContextFactory = $salesChannelContextFactory;
        $this->emailService = $emailService;
    }

    public static function getSubscribedEvents(): array
    {
        return [
            OrderWrittenEvent::class => 'onOrderWritten',
        ];
    }

    // onOrderWritten方法...
}

3. 创建合法的SalesChannelContext实例

使用工厂类的create方法,结合订单参数生成符合要求的上下文实例:

use Shopware\Core\Framework\Context;

// 在onOrderWritten方法内,拿到订单参数后执行
$systemContext = Context::createDefaultContext();

$salesChannelContext = $this->salesChannelContextFactory->create(
    $salesChannelId,
    $customerId ?? '', // 订单关联用户则传用户ID,否则传空字符串表示匿名用户
    [
        'languageId' => $languageId,
        'currencyId' => $currencyId,
        // 可按需添加其他上下文参数,比如付款方式、配送方式ID等
    ],
    $systemContext
);

4. 调用邮件服务发送邮件

现在你拿到的是标准的SalesChannelContext实例,直接传给邮件服务即可:

$this->emailService->sendMail(
    'your-custom-mail-template-id', // 替换为你的邮件模板ID
    $order->getOrderCustomer()->getEmail(), // 从订单取收件人邮箱
    ['order' => $order], // 邮件模板所需的数据
    [], // 抄送/密送等可选参数
    $salesChannelContext
);

为什么之前调用Store API不行?

Store API返回的是序列化后的stdClass对象,属于对外暴露的数据传输对象(DTO),并非Shopware内部使用的SalesChannelContext实体类实例,类型不匹配自然会触发TypeError。必须通过内置工厂类创建内部上下文对象。

内容的提问来源于stack exchange,提问作者Ibrahima sory Camara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 13:46:04