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
相关产品推荐
相关产品推荐

