Magento 2:产品存储库,过滤器组和“与”


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过滤器应用为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/…可能会有用。
艾伦·肯特

Answers:



2

在Magento 2中,相同的所有过滤器FilterGroup都将使用OR运算符添加。但是所有这些FilterGroup将使用AND运算符添加。因此,您将需要添加多个FilterGroup,如下所示:

$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中的默认存储。先生,您是否有理由宣布错误?
卡马尔·辛格


@Alan Storm,这就是我在回答中提到的内容。根据Magento 2搜索条件文档,使用AND运算符连接所有过滤器组,使用OR运算符连接单个过滤器组中的所有过滤器。我已经提到过,此解决方案已使用默认存储进行了测试。根据您的评论,使此答案错误的原因是什么,我没有明白。
卡马尔·辛格

@KamelSingh您阅读了我链接的错误报告吗?不论其既定的行为,过滤器和过滤器组的行为最终取决于存储库的行为,他们就能加入。
艾伦风暴
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.