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
相关产品推荐
相关产品推荐

