Shopware 6:通过编程方式使用规则筛选订单
Shopware 6插件规则筛选订单问题解决思路
问题背景
我正在开发一款Shopware 6插件,核心需求是通过规则构建器选择需要处理的订单:在插件设置中选定规则后,在Symfony控制台命令、消息队列任务及定时任务中加载该规则,按规则筛选系统内所有订单,再传递给后续服务处理。
目前尝试加载规则后将其添加到上下文,但使用仓储搜索订单时未实现过滤效果,代码如下:
$orderRule = $this->helperService->getOrderRule($this->context); if ($orderRule) { $this->context->setRuleIds([$orderRule->getId()]); } $criteria = new Criteria(); $result = $this->orderRepository->search($criteria, $this->context)->getEntities();
查看Shopware核心代码后未找到常规规则的直接应用位置,怀疑过滤逻辑是在DAL结果加载后执行。另外,由于Symfony命令默认没有Shopware上下文,我试过使用Context::createDefaultContext(),也考虑过通过SalesChannelContextFactory自行创建SalesChannelContext。
问题根源
Shopware的规则系统默认面向销售渠道场景设计,直接给普通Context设置规则ID不会自动触发订单过滤——规则的匹配逻辑并非直接作用于DAL的查询阶段,需要手动调用规则匹配服务,或转换规则条件为查询筛选器来实现过滤。
正确实现方案
方式一:用RuleMatcher筛选已查询订单
适合订单数量较少的场景,通过规则匹配服务逐个校验订单:
// 注入RuleMatcher和SalesChannelContextFactory服务 private RuleMatcher $ruleMatcher; private SalesChannelContextFactory $salesChannelContextFactory; // ... $orderRule = $this->helperService->getOrderRule($this->context); if (!$orderRule) { return; } // 查询目标范围的订单(可添加分页、基础筛选条件) $criteria = new Criteria(); $orders = $this->orderRepository->search($criteria, $this->context)->getEntities(); // 筛选符合规则的订单 $matchingOrders = []; foreach ($orders as $order) { // 为订单创建对应销售渠道的上下文 $salesChannelContext = $this->salesChannelContextFactory->create( $order->getSalesChannelId(), $this->context->getLanguageId(), $this->context->getCurrencyId() ); if ($this->ruleMatcher->match($orderRule, $salesChannelContext, ['order' => $order])) { $matchingOrders[] = $order; } }
方式二:将规则条件转换为DAL查询Criteria
适合订单数量较多的场景,直接在查询阶段过滤,提升效率:
// 注入RuleConditionConverter服务 private RuleConditionConverter $ruleConditionConverter; // ... $orderRule = $this->helperService->getOrderRule($this->context); if (!$orderRule) { return; } // 将规则条件转换为DAL可识别的过滤条件 $condition = $this->ruleConditionConverter->convertToCriteria($orderRule->getConditions(), $this->context); $criteria = new Criteria(); $criteria->addFilter($condition); // 直接查询符合规则的订单 $matchingOrders = $this->orderRepository->search($criteria, $this->context)->getEntities();
注意事项
- 在控制台/定时任务中创建
SalesChannelContext时,必须传入正确的销售渠道ID、语言ID、货币ID,否则规则匹配可能出现错误 - 若规则包含依赖销售渠道配置的条件,需使用对应销售渠道的上下文进行匹配
- 大数量订单场景优先使用方式二,避免内存占用过高
内容的提问来源于stack exchange,提问作者Marco Stastny
相关产品推荐
相关产品推荐

