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

Shopware 6如何在Criteria中筛选属性选项及后台配置建议

解决Shopware 6属性选项筛选及后台配置规则问题

一、正确筛选/排除属性选项的方法

你当前的错误在于关联和过滤路径不对,Shopware 6中产品的属性选项关联路径是properties.options,而非直接properties.name或options.name。要针对属性选项做过滤,需要调整关联和过滤逻辑:

1. 修正关联与过滤代码

修改onListingCriteria方法中的关联和过滤部分:

public function onListingCriteria(ProductListingCriteriaEvent $event): void
{
    // 关联属性组、属性以及属性选项
    $criteria = $event->getCriteria();
    $criteria->addAssociation('properties.group');
    $criteria->addAssociation('properties.options'); // 新增属性选项关联

    $filters = $criteria->getExtension('filters');
    if (!$filters instanceof FilterCollection) {
        return;
    }

    $propertyFilter = $filters->get('properties');
    if (!$propertyFilter instanceof Filter || !\is_array($propertyFilter->getValues())) {
        return;
    }

    $currentPropertyOptions = $propertyFilter->getValues();

    // 当选中指定属性选项ID时,排除目标属性选项
    if (in_array('c0d02d1738fd4293a489695787e06b5c', $currentPropertyOptions)) {
        // 用EqualsFilter针对属性选项ID过滤,比PrefixFilter更精准
        $criteria->addFilter(
            new NotFilter(
                NotFilter::CONNECTION_OR,
                [
                    // 替换成你的目标选项ID
                    new EqualsFilter('properties.options.id', '目标选项ID1'),
                    new EqualsFilter('properties.options.id', '目标选项ID2')
                ]
            )
        );
    }
}

关键说明

  • 属性选项的正确关联路径是properties.options,必须显式关联才能过滤
  • 用EqualsFilter针对选项ID过滤比名称更稳定,避免名称变更导致失效
  • 如果需要按选项名称过滤,路径应为properties.options.name,而非product.properties.name

二、实现后台可配置的关联规则

要实现后台可配置的“选中A属性的X选项时,才显示B属性的Y/Z选项”规则,需要做以下几步:

1. 创建后台配置实体

创建一个自定义实体(比如PropertyDependencyRule),存储以下字段:

  • triggerPropertyOptionId: 触发规则的属性选项ID(用户选中的选项)
  • targetPropertyGroupId: 目标属性组ID(要控制的属性所属组)
  • allowedOptionIds: 允许显示的属性选项ID列表(多选)

2. 生成后台配置界面

通过Shopware的Admin SDK创建自定义模块,在后台添加规则配置页面,让管理员可以选择触发选项、目标属性组以及允许的选项。

3. 修改Subscriber逻辑加载配置

在onListingCriteria方法中,注入自定义实体的Repository,加载所有生效的规则,动态生成过滤条件:

// 注入PropertyDependencyRuleRepository和PropertyGroupRepository
private $ruleRepository;
private $propertyGroupRepository;

public function __construct(
    PropertyDependencyRuleRepository $ruleRepository,
    PropertyGroupRepository $propertyGroupRepository
) {
    $this->ruleRepository = $ruleRepository;
    $this->propertyGroupRepository = $propertyGroupRepository;
}

public function onListingCriteria(ProductListingCriteriaEvent $event): void
{
    $criteria = $event->getCriteria();
    $criteria->addAssociation('properties.group');
    $criteria->addAssociation('properties.options');

    $filters = $criteria->getExtension('filters');
    if (!$filters instanceof FilterCollection) {
        return;
    }

    $propertyFilter = $filters->get('properties');
    if (!$propertyFilter instanceof Filter || !\is_array($propertyFilter->getValues())) {
        return;
    }

    $currentSelectedOptionIds = $propertyFilter->getValues();

    // 加载所有匹配当前选中选项的规则
    $ruleCriteria = new Criteria();
    $ruleCriteria->addFilter(new EqualsAnyFilter('triggerPropertyOptionId', $currentSelectedOptionIds));
    $rules = $this->ruleRepository->search($ruleCriteria, $event->getContext())->getEntities();

    foreach ($rules as $rule) {
        // 获取目标属性组下所有选项ID,排除规则中允许的选项之外的部分
        $targetGroupCriteria = new Criteria([$rule->getTargetPropertyGroupId()]);
        $targetGroupCriteria->addAssociation('options');
        $targetGroup = $this->propertyGroupRepository->search($targetGroupCriteria, $event->getContext())->first();
        
        if (!$targetGroup) continue;

        $allOptionIds = $targetGroup->getOptions()->map(fn($opt) => $opt->getId())->getArrayCopy();
        $disallowedOptionIds = array_diff($allOptionIds, $rule->getAllowedOptionIds());

        if (!empty($disallowedOptionIds)) {
            $criteria->addFilter(
                new NotFilter(
                    NotFilter::CONNECTION_OR,
                    array_map(fn($id) => new EqualsFilter('properties.options.id', $id), $disallowedOptionIds)
                )
            );
        }
    }
}

4. 适配前端过滤选项

如果需要在前端属性筛选器中隐藏禁用的选项,还要监听ProductListingResultEvent,修改返回的过滤选项集合,移除不符合规则的选项。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 20:05:24