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

Shopware 6:如何隐藏无对应客户组价格规则的商品?

Shopware 6 隐藏无对应客户组价格规则的商品实现方案

要实现无当前客户组价格规则的商品完全隐藏(包括列表、搜索、深度链接访问),需要从「列表过滤」和「详情页拦截」两方面入手,以下是具体实现步骤:

一、利用ProductListingCollectFilterEvent过滤商品列表

通过该事件给商品查询添加过滤条件,只保留当前客户组有价格规则的商品:

  1. 创建事件订阅者类
<?php

namespace YourPlugin\Core\Content\Product\EventSubscriber;

use Shopware\Core\Content\Product\Event\ProductListingCollectFilterEvent;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\InFilter;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class ProductCustomerGroupFilterSubscriber implements EventSubscriberInterface
{
    private EntityRepository $productPriceRepository;

    public function __construct(EntityRepository $productPriceRepository)
    {
        $this->productPriceRepository = $productPriceRepository;
    }

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

    public function addCustomerGroupPriceFilter(ProductListingCollectFilterEvent $event): void
    {
        $context = $event->getSalesChannelContext();
        $criteria = $event->getCriteria();
        $currentCustomerGroupId = $context->getCustomerGroup()->getId();

        // 查询当前客户组有价格规则的所有商品ID
        $priceCriteria = new Criteria();
        $priceCriteria->addFilter(new EqualsFilter('customerGroupId', $currentCustomerGroupId));
        $priceCriteria->setFields(['productId']);

        $productPriceEntities = $this->productPriceRepository->search($priceCriteria, $context->getContext());
        $allowedProductIds = $productPriceEntities->getEntities()->map(fn($price) => $price->getProductId());

        // 如果没有允许的商品,直接添加空过滤
        if (empty($allowedProductIds)) {
            $criteria->addFilter(new InFilter('id', []));
            return;
        }

        // 添加过滤条件,只保留有对应价格规则的商品
        $criteria->addFilter(new InFilter('id', $allowedProductIds));
    }
}
  1. 注册订阅者
    在src/Resources/config/services.xml中添加服务定义:
<service id="YourPlugin\Core\Content\Product\EventSubscriber\ProductCustomerGroupFilterSubscriber">
    <argument type="service" id="product_price.repository"/>
    <tag name="kernel.event_subscriber"/>
</service>

二、拦截商品详情页访问

仅过滤列表还不够,用户通过深度链接直接访问商品详情页时,需要额外拦截:

  1. 监听ProductLoadedEvent,移除无对应价格规则的商品
<?php

namespace YourPlugin\Core\Content\Product\EventSubscriber;

use Shopware\Core\Content\Product\Event\ProductLoadedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class ProductDetailCustomerGroupFilterSubscriber implements EventSubscriberInterface
{
    private EntityRepository $productPriceRepository;

    public function __construct(EntityRepository $productPriceRepository)
    {
        $this->productPriceRepository = $productPriceRepository;
    }

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

    public function filterProductByCustomerGroupPrice(ProductLoadedEvent $event): void
    {
        $context = $event->getSalesChannelContext();
        $currentCustomerGroupId = $context->getCustomerGroup()->getId();
        $products = $event->getProducts();

        foreach ($products as $key => $product) {
            // 检查当前商品是否有对应客户组的价格规则
            $priceCriteria = new Criteria();
            $priceCriteria->addFilter(new EqualsFilter('customerGroupId', $currentCustomerGroupId));
            $priceCriteria->addFilter(new EqualsFilter('productId', $product->getId()));
            $priceCount = $this->productPriceRepository->search($priceCriteria, $context->getContext())->getTotal();

            if ($priceCount === 0) {
                // 移除无价格规则的商品,前端会显示404
                unset($products[$key]);
            }
        }

        $event->setProducts($products);
    }
}
  1. 同样在services.xml中注册该订阅者:
<service id="YourPlugin\Core\Content\Product\EventSubscriber\ProductDetailCustomerGroupFilterSubscriber">
    <argument type="service" id="product_price.repository"/>
    <tag name="kernel.event_subscriber"/>
</service>

三、注意事项

  • 缓存处理:Shopware的商品列表和详情页会有缓存,需要确保缓存键包含客户组ID,避免不同客户组看到错误的商品。默认情况下Shopware已经会根据客户组区分缓存,无需额外配置。
  • 匿名用户场景:上述代码会自动适配匿名用户的客户组(默认是guest组),只有给匿名组配置了对应价格规则的商品才会显示。
  • 搜索结果过滤:ProductListingCollectFilterEvent会覆盖搜索、分类页等所有商品列表场景,无需额外处理搜索逻辑。

内容的提问来源于stack exchange,提问作者Philip

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 04:05:28