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

Symfony(Shopware 6)订阅者类中函数存取数组的问题求助

在Shopware 6的Subscriber类中设置和获取数组变量的问题

我需要在Shopware 6的Subscriber类里通过函数设置和获取数组变量,目前碰到以下问题:

  • 能通过构造函数存取私有数组变量,但没法在函数里用$this->设置该变量;
  • 构造函数注入数组参数会导致URL无响应,移除后恢复正常;
  • 尝试自定义方法赋值数组的方式无效;
  • 调整代码后,依然无法在onListingCriteria方法中获取onListingResult方法设置的数组,我的目标是根据选中的属性选项修改Criteria。

相关代码

当前Subscriber类代码

<?php declare(strict_types=1);

namespace CustomFilter\Subscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Content\Product\Events\ProductListingResultEvent;
use Shopware\Core\Content\Product\Events\ProductListingCriteriaEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\Context;
use Symfony\Component\HttpFoundation\Request;
use Shopware\Core\Content\Product\SalesChannel\Listing\Filter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Bucket\FilterAggregation;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Metric\MaxAggregation;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\ContainsFilter;
use Shopware\Core\Framework\Struct\ArrayEntity;

class Subscriber implements EventSubscriberInterface
{
    private $currentProperty1;

    public function __construct(array $currentProperty1)
    {
        $this->currentProperty1 = $currentProperty1;
    }

    public static function getSubscribedEvents(): array
    {
        return [
            ProductListingResultEvent::class => 'handleResult',
            ProductListingCriteriaEvent::class => 'handleRequest'
        ];
    }

    public function handleResult(ProductListingResultEvent $event)
    {
        $properties = $event->getResult();
        $this->currentProperty1 = $properties->getCurrentFilter('properties');
    }

    public function handleRequest(ProductListingCriteriaEvent $event): void
   {
        $event->getCriteria()->addAssociation('properties');
        $event->getCriteria()->addAssociation('properties.group');

        $currentProperty1 = $this->currentProperty1;

        if (in_array('c0d02d1738fd4293a489695787e06b5c', $currentProperty1)) {
            $friteria = $event->getCriteria();

            $friteria->addFilter(new MultiFilter(
                MultiFilter::CONNECTION_OR,
                    [
                        new ContainsFilter('product.properties.name', 'PropertyNameA'),
                        new ContainsFilter('product.properties.name', 'PropertyNameB')
                    ]
                )
            );
        }
   }
}

尝试的简化代码(无法设置变量)

class Subscriber implements EventSubscriberInterface
{
    private $currentProperty1;

    public function handleRequest(ProductListingCriteriaEvent $event): void
   {
        // 此处获取
        $array1 = array ($this->currentProperty1);
   }

    public function handleResult(ProductListingResultEvent $event)
    {
        // 此处设置
        $this->currentProperty1 = $currentProperty1;
    }
}

带仓库注入的构造函数(导致URL无响应)

private $propertyGroupRepository;
private array $currentProperty1;

public function __construct(EntityRepositoryInterface $propertyGroupRepository, array $currentProperty1)
{
    $this->propertyGroupRepository = $propertyGroupRepository;
    $this->currentProperty1 = $currentProperty1;
}

尝试自定义方法赋值(无效)

class Subscriber implements EventSubscriberInterface {

    public function setCurrent()
    {
        $array1 = array(1 => 'item 1', 2 => 'item 2');
        return $array1;
    }

    private $currentProperty1;

    public function __construct()
    {
        $this->currentProperty1 = new setCurrent();
    }
}

调整后的最新代码(仍无法传递数组)

<?php // declare(strict_types=1);

namespace CustomFilterBasedOnSelectedOption\Subscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Content\Product\Events\ProductListingResultEvent;
use Shopware\Core\Content\Product\Events\ProductListingCriteriaEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\Context;
use Symfony\Component\HttpFoundation\Request;
use Shopware\Core\Content\Product\SalesChannel\Listing\Filter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Bucket\FilterAggregation;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Metric\MaxAggregation;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\ContainsFilter;
use Shopware\Core\Framework\Struct\ArrayEntity;

class Subscriber implements EventSubscriberInterface
{
    private ?array $currentPropertyOptions = null;

    public static function getSubscribedEvents(): array
    {
        return [
            ProductListingCriteriaEvent::class => 'onListingCriteria',
            ProductListingResultEvent::class => 'onListingResult'
        ];
    }

        public function onListingResult(ProductListingResultEvent $event)
    {
        $this->currentPropertyOptions = ['foo', 'bar', 'baz'];

        /*
        $properties = $event->getResult();
        $currentPropertyOptions = $properties->getCurrentFilter('properties');
        */
    }

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

        $currentPropertyOptions = $this->currentPropertyOptions;

        /*
        if (in_array('c0d02d1738fd4293a489695787e06b5c', $currentPropertyOptions)) {
            $criteria = $event->getCriteria();

            $criteria->addFilter(new MultiFilter(
                MultiFilter::CONNECTION_OR,
                    [
                        new ContainsFilter('product.properties.name', 'Option1'),
                        new ContainsFilter('product.properties.name', 'Option2')
                    ]
                )
            );
        }
        */

        $event->getContext()->addExtension('currentPropertyOptionsCriteria', new ArrayEntity($currentPropertyOptions));
   }
}

问题分析与解决办法

1. 核心问题:事件执行顺序搞反了

Shopware的商品列表事件触发顺序是:

  • ProductListingCriteriaEvent:先触发,用于构建数据库查询条件;
  • ProductListingResultEvent:后触发,用于处理数据库返回的结果。

你之前的代码先执行onListingCriteria,再执行onListingResult,导致onListingCriteria里的变量永远是初始值(null),因为赋值逻辑还没执行。

2. 构造函数注入数组的问题

Symfony/Shopware的DI容器不能直接注入未配置的数组参数:

  • 如果只是初始化空数组,直接在类里定义即可:private array $currentPropertyOptions = [];;
  • 如果需要注入配置好的数组,要在services.yaml里明确配置:
    services:
        CustomFilterBasedOnSelectedOption\Subscriber\Subscriber:
            arguments:
                $currentPropertyOptions: ['foo', 'bar']
    

3. 正确获取选中属性的方式

要在构建Criteria时获取用户选中的属性,直接从请求参数里拿,不需要依赖后续事件:

public function onListingCriteria(ProductListingCriteriaEvent $event): void
{
    $request = $event->getRequest();
    // Shopware默认用'properties'作为属性过滤的参数名
    $selectedProperties = $request->query->get('properties', []);
    
    // 防止参数不是数组导致报错
    if (!is_array($selectedProperties)) {
        $selectedProperties = [];
    }

    if (in_array('c0d02d1738fd4293a489695787e06b5c', $selectedProperties)) {
        $criteria = $event->getCriteria();
        $criteria->addFilter(new MultiFilter(
            MultiFilter::CONNECTION_OR,
            [
                new ContainsFilter('properties.name', 'Option1'),
                new ContainsFilter('properties.name', 'Option2')
            ]
        ));
    }
}

4. 类内变量赋值的正确写法

  • 简化代码里的handleResult方法存在未定义变量$currentProperty1,正确写法是从事件对象取值:
    public function handleResult(ProductListingResultEvent $event)
    {
        $properties = $event->getResult();
        $this->currentProperty1 = $properties->getCurrentFilter('properties');
    }
    
  • 自定义方法赋值错误地用了new setCurrent(),调用类方法应该用$this->setCurrent():
    public function __construct()
    {
        $this->currentProperty1 = $this->setCurrent();
    }
    

最终修正后的Subscriber代码

<?php declare(strict_types=1);

namespace CustomFilterBasedOnSelectedOption\Subscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Content\Product\Events\ProductListingCriteriaEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\ContainsFilter;

class Subscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            ProductListingCriteriaEvent::class => 'onListingCriteria'
        ];
    }

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

        // 直接从请求获取选中的属性选项
        $selectedProperties = $event->getRequest()->query->get('properties', []);
        
        // 确保是数组类型,避免in_array报错
        if (!is_array($selectedProperties)) {
            $selectedProperties = [];
        }

        if (in_array('c0d02d1738fd4293a489695787e06b5c', $selectedProperties)) {
            $criteria = $event->getCriteria();
            $criteria->addFilter(new MultiFilter(
                MultiFilter::CONNECTION_OR,
                [
                    new ContainsFilter('properties.name', 'Option1'),
                    new ContainsFilter('properties.name', 'Option2')
                ]
            ));
        }
    }
}

内容的提问来源于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 11:37:35