Magento 2: сховища продуктів, групи фільтрів та `AND`


12

Я намагаюся використовувати сховище продуктів для отримання списку продуктів. Я хочу взяти на основі двох фільтрів у поєднанні з ANDкритеріями, але, здається, не працює. Не розумію, як працюють групи фільтрів? Або це помилка, про яку слід повідомити?

Зокрема, (дурний приклад для простоти) у мене є конструктор, куди я вводить конструктор фільтрів, конструктор групи фільтрів та конструктор критеріїв пошуку

public function __construct(
    \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
    \Magento\Framework\Api\FilterBuilder $filterBuilder,
    \Magento\Framework\Api\Search\FilterGroupBuilder $filterGroupBuilder 
)
{
    $this->searchCriteriaBuilder = $searchCriteriaBuilder;
    $this->filterBuilder         = $filterBuilder;
    $this->filterGroupBuilder    = $filterGroupBuilder;
}

Потім, згодом у методі, я використовую конструктори фільтрів, щоб побудувати два фільтри

    $filter1 = $this->filterBuilder->setField('sku')
            ->setValue('24-MB01')
            ->setConditionType('eq')
            ->create();

    $filter2 = $this->filterBuilder->setField('sku')
            ->setValue('WT08-XS-Black')
            ->setConditionType('eq')
            ->create();

Потім я використовую конструктор групи фільтрів для створення групи фільтрів, яка складається з цих двох фільтрів

    $filter_group = $this->filterGroupBuilder
        ->addFilter($filter1)
        ->addFilter($filter2)
        ->create();

Потім я скористався конструктором критеріїв пошуку, встановив на ньому групу фільтрів

    $criteria = $this->searchCriteriaBuilder
        ->setFilterGroups([$filter_group])
        ->setPageSize(100)
        ->create();            
    return $criteria

Нарешті, коли я використовую ці критерії з продуктовим сховищем (використовується в іншому місці, виключаючи конструктор і di, щоб уникнути плутанини)

/* @var Magento\Catalog\Api\ProductRepositoryInterface */
$list = $productRepository->getList($searchCriteria);  

Дзвінок успішний, але я отримую два продукти. тобто фільтр SKU застосовувався як a OR, а не як AND. Я очікую, що цей запит нічого не поверне.

Якщо я вкопаюсь до Magento\Catalog\Api\ProductRepositoryкласу, і погляну на вибраний склад колекції

protected function addFilterGroupToCollection(
    \Magento\Framework\Api\Search\FilterGroup $filterGroup,
    Collection $collection
) {
    //...
    if ($fields) {
        $collection->addFieldToFilter($fields);
    }

    //printf lives in my heart forever
    echo($collection->getSelect()->__toString());
    exit;
}               

Я бачу критерії, додані з OR

SELECT `e`.*, IF(at_status.value_id > 0, at_status.value, at_status_default.value) AS `status`, IF(at_visibility.value_id > 0, at_visibility.value, at_visibility_default.value) AS `visibility` 

FROM `catalog_product_entity` AS `e` 

INNER JOIN `catalog_product_entity_int` AS `at_status_default` ON (`at_status_default`.`entity_id` = `e`.`entity_id`) AND (`at_status_default`.`attribute_id` = '94') AND `at_status_default`.`store_id` = 0 LEFT JOIN `catalog_product_entity_int` AS `at_status` ON (`at_status`.`entity_id` = `e`.`entity_id`) AND (`at_status`.`attribute_id` = '94') AND (`at_status`.`store_id` = 1) 

INNER JOIN `catalog_product_entity_int` AS `at_visibility_default` ON (`at_visibility_default`.`entity_id` = `e`.`entity_id`) AND (`at_visibility_default`.`attribute_id` = '96') AND `at_visibility_default`.`store_id` = 0 LEFT JOIN `catalog_product_entity_int` AS `at_visibility` ON (`at_visibility`.`entity_id` = `e`.`entity_id`) AND (`at_visibility`.`attribute_id` = '96') AND (`at_visibility`.`store_id` = 1)

WHERE ((`e`.`sku` = '24-MB01') OR (`e`.`sku` = 'WT08-XS-Black')) 

Це помилка? Чи існує спосіб (не покладаючись безпосередньо на колекції продуктів та виривання сховищ), щоб зробити цю роботу?


2
Я особисто ще не заглядав у цю сферу, але cyrillschumacher.com/2015/01/02/… може бути корисним.
Алан Кент

Відповіді:


15

Фактична анотація \Magento\Framework\Api\Search\FilterGroupтверджень (клас phpDoc):

Згрупуйте два або більше фільтрів разом, використовуючи логічну АБО

Це означає, що вам потрібно створити дві групи з одним фільтром у кожній.


Дякуємо, що роз'яснили це. Ви просто полюбили всі шари абстракції в Magento 2 :-P
Giel Berkers

2

У Magento 2 всі фільтри в тому ж самому FilterGroupбудуть додані за допомогою ORоператора. Але все FilterGroupбуде додано за допомогою ANDоператора. Тому вам потрібно буде додати декілька FilterGroups, як показано нижче:

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$searchCriteria = $objectManager->create('\Magento\Framework\Api\SearchCriteria');
$filter = $objectManager->create('\Magento\Framework\Api\Filter');
$filter->setField('category_id');
$filter->setValue(array(1, 2, 3));
$filter->setConditionType('in');

$filterGroup = $objectManager->create('\Magento\Framework\Api\Search\FilterGroup');
$filterGroup->setFilters([$filter]);

$filterEnabled = $objectManager->create('\Magento\Framework\Api\Filter');
$filterEnabled->setField('status');
$filterEnabled->setValue(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED);
$filterEnabled->setConditionType('eq');

$filterGroupEnabled = $objectManager->create('\Magento\Framework\Api\Search\FilterGroup');
$filterGroupEnabled->setFilters([$filterEnabled]);


$searchCriteria->setFilterGroups([$filterGroup, $filterGroupEnabled]);

Більш детальну інформацію та логічні комбінації щодо критеріїв пошуку ви можете знайти за критеріями пошуку Magento-2


Це неправильно. Логіка реалізована на основі сховища.
Алан Шторм

Привіт @Alan Storm, це перевірене рішення. Я перевірив це на магазин за замовчуванням у Magento 2.1.0. Чи є у вас виправдання, щоб визнати це неправильним, сер?
Камал Сінгх

@karnalsingh Ця помилка: github.com/magento/magento2/isissue/4287
Alan Storm

@Alan Storm, саме про це я і згадував у своїй відповіді. Усі групи фільтрів з'єднуються за допомогою оператора AND, а всі фільтри в одній групі фільтрів з'єднуються за допомогою оператора АБО відповідно до документації щодо критеріїв Magento 2. Я вже згадував, що це рішення тестується в магазині за замовчуванням. Що робить цю відповідь неправильною відповідно до вашого коментаря, я не зрозумів.
Камал Сінгх

@KamelSingh Ви читали звіт про помилку, з яким я пов’язаний? Незалежно від їх наміченої поведінки, поведінка фільтрів і груп фільтрів в кінцевому рахунку залежить від поведінки сховища, в якому вони знаходяться.
Алан Шторм
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.