Shopware 6支付方式索引无限循环问题求助
Shopware支付方式索引队列无限循环问题排查与解决
问题原因分析
这个无限循环的核心逻辑链是:
- 队列中的
PaymentMethodIndexingMessage被PaymentIndexer处理时,会调用PaymentDistinguishableNameGenerator::generateDistinguishablePaymentNames方法。 - 该方法内部会对支付方式实体执行
upsert操作,更新distinguishable_name字段。 - Shopware的索引机制会监听支付方式实体的变更事件,一旦检测到实体被修改,就会自动生成新的
PaymentMethodIndexingMessage放入队列。 - 新消息被处理时又会重复上述流程,最终形成无限循环。
这个问题在Shopware 6.4.x到6.5.6.1版本中均存在,本质是索引逻辑与实体修改逻辑形成了闭环触发。
解决方案
以下是几种可行的解决思路,按推荐优先级排序:
方案1:通过装饰器跳过索引上下文的实体修改
使用Shopware的装饰器机制重写PaymentDistinguishableNameGenerator,在索引过程中跳过upsert操作,从源头切断循环:
<?php namespace YourPlugin\Core\Checkout\Payment\DataAbstractionLayer; use Shopware\Core\Checkout\Payment\DataAbstractionLayer\PaymentDistinguishableNameGenerator; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent; class DecoratedPaymentDistinguishableNameGenerator extends PaymentDistinguishableNameGenerator { public function generateDistinguishablePaymentNames(EntityWrittenContainerEvent $event, Context $context): void { // 检测当前上下文是否为索引上下文,是则跳过修改操作 if ($context->getExtension('indexing')) { return; } parent::generateDistinguishablePaymentNames($event, $context); } }
接着在插件的services.xml中注册装饰器:
<service id="YourPlugin\Core\Checkout\Payment\DataAbstractionLayer\DecoratedPaymentDistinguishableNameGenerator" decorates="Shopware\Core\Checkout\Payment\DataAbstractionLayer\PaymentDistinguishableNameGenerator"> <argument type="service" id="YourPlugin\Core\Checkout\Payment\DataAbstractionLayer\DecoratedPaymentDistinguishableNameGenerator.inner"/> </service>
方案2:修改索引器忽略特定字段变更
自定义PaymentIndexer,让其忽略distinguishable_name字段的变更触发:
- 创建自定义索引器继承原
PaymentIndexer,重写getTriggeredEntities或update方法,过滤掉distinguishable_name字段的变更。 - 替换原索引器服务,确保自定义索引器生效。
这种方式适合不需要完全关闭可区分名称自动生成,但要避免索引循环的场景。
方案3:手动管理可区分名称并关闭自动生成
如果业务允许,可以在支付方式创建/更新时手动设置distinguishable_name字段,然后禁用PaymentDistinguishableNameGenerator服务,彻底避免自动修改操作:
在插件的services.xml中添加:
<service id="Shopware\Core\Checkout\Payment\DataAbstractionLayer\PaymentDistinguishableNameGenerator" public="false"> <argument type="service" id="Shopware\Core\Framework\DataAbstractionLayer\Write\EntityWriter"/> <argument type="service" id="Shopware\Core\Checkout\Payment\PaymentMethodRepository"/> <argument type="service" id="Shopware\Core\System\Language\LanguageRepository"/> </service>
然后将该服务的实现替换为一个空方法的类,或者直接设置disabled="true"(需注意版本兼容性)。
内容的提问来源于stack exchange,提问作者newgennerd
相关产品推荐
相关产品推荐

