Shopware 6:如何隐藏无对应客户组价格规则的商品?
Shopware 6 隐藏无对应客户组价格规则的商品实现方案
要实现无当前客户组价格规则的商品完全隐藏(包括列表、搜索、深度链接访问),需要从「列表过滤」和「详情页拦截」两方面入手,以下是具体实现步骤:
一、利用ProductListingCollectFilterEvent过滤商品列表
通过该事件给商品查询添加过滤条件,只保留当前客户组有价格规则的商品:
- 创建事件订阅者类
<?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)); } }
- 注册订阅者
在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>
二、拦截商品详情页访问
仅过滤列表还不够,用户通过深度链接直接访问商品详情页时,需要额外拦截:
- 监听
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); } }
- 同样在
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
相关产品推荐
相关产品推荐

