Shopware 6模板间变量传递问题:快速视图中无法灰化缺货商品
你遇到的核心问题是:商品详情页的page.unavailable变量是由商品详情页路由(ProductDetailRoute)生成并传递的,但快速视图的加载逻辑完全独立,默认不会包含这个缺货变体ID集合。你在模板里通过sw_include传递变量的尝试无效,因为父模板里的page.unavailable本身在快速视图上下文里就不存在。
要解决这个问题,需要从后端补充快速视图的缺货数据,再在模板中适配使用,具体步骤如下:
1. 后端:给快速视图添加缺货变体ID集合
Shopware提供了专门的事件来扩展快速视图的数据,我们可以通过监听ProductQuickViewLoaderEvent来添加缺货变体的ID集合。
步骤1:创建事件订阅器
在你的自定义插件中创建一个订阅器类,用来处理快速视图的数据扩展:
<?php namespace YourPluginNamespace\Subscriber; use Shopware\Core\Content\Product\SalesChannel\QuickView\ProductQuickViewLoaderEvent; use Shopware\Core\System\SalesChannel\SalesChannelContext; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class ProductQuickViewUnavailableSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents(): array { return [ ProductQuickViewLoaderEvent::class => 'addUnavailableVariantsToQuickView', ]; } public function addUnavailableVariantsToQuickView(ProductQuickViewLoaderEvent $event): void { $product = $event->getProduct(); $salesChannelContext = $event->getSalesChannelContext(); $page = $event->getResult(); // 生成缺货变体ID集合(逻辑和详情页保持一致) $unavailableVariantIds = $this->collectUnavailableVariantIds($product, $salesChannelContext); // 将数据添加到page对象,让模板可以访问 $page->setExtension('unavailable', $unavailableVariantIds); } private function collectUnavailableVariantIds($product, SalesChannelContext $context): array { $unavailableIds = []; // 仅处理有变体的父商品 if (!$product->getChildren() || !$product->getParentId()) { return $unavailableIds; } foreach ($product->getChildren() as $variant) { // 根据Shopware的库存规则判断是否缺货 $stock = $variant->getStock(); $allowOutOfStock = $variant->getAllowOutOfStock(); $isActive = $variant->isActive(); // 变体未激活 或 库存为0且不允许缺货购买,视为不可用 if (!$isActive || ($stock <= 0 && !$allowOutOfStock)) { $unavailableIds[] = $variant->getId(); } } return $unavailableIds; } }
步骤2:注册订阅器
在插件的services.xml(或services.yaml)中注册这个订阅器:
<service id="YourPluginNamespace\Subscriber\ProductQuickViewUnavailableSubscriber"> <tag name="kernel.event_subscriber"/> </service>
2. 模板:适配快速视图的变量
现在快速视图的page对象已经有了page.extensions.unavailable数据,需要修改configurator.html.twig中的判断逻辑,同时兼容详情页和快速视图的上下文:
{# 先统一获取缺货ID集合,兼容详情页和快速视图 #} {% set unavailableVariantIds = page.unavailable ?? page.extensions.unavailable ?? [] %} <div class="product-detail-configurator-option {% if option.id in unavailableVariantIds %}grau-labels{% endif %}"> {% block page_product_detail_configurator_option_radio %} <input type="radio" name="{{ group.id }}" value="{{ option.id }}" class="product-detail-configurator-option-input{% if isCombinableCls %} {{ isCombinableCls }}{% endif %}" title="{{ optionIdentifier }}" id="{{ optionIdentifier }}" {% if isActive %} checked="checked" {% endif %}> </div> {% endblock %}
3. 移除无效的变量传递
现在不需要在sw_include中手动传递notinhere变量了,因为我们已经通过后端统一了数据来源,可以删除之前添加的with {notinhere : page.unavailable}代码。
你之前在模板中传递变量的思路没问题,但前提是父模板里的page.unavailable必须存在。而快速视图的加载逻辑默认不会生成这个变量,所以传递的是null,自然无法触发置灰效果。只有通过后端扩展快速视图的数据,才能从根源解决问题。
内容的提问来源于stack exchange,提问作者user17787214

