Magento 2:製品リポジトリ、フィルターグループ、および「AND」


12

製品のリストを取得するために製品リポジトリを使用しようとしています。AND条件と組み合わせた2つのフィルターに基づいて取得したいのですが、うまくいかないようです。フィルターグループの仕組みを理解できませんか?または、これは報告されるべきバグですか?

具体的には、(簡単にするために愚かな例)フィルタービルダー、フィルターグループビルダー、および検索条件ビルダーを挿入するコンストラクターがあります。

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;
}

次に、メソッドの後半で、フィルタービルダーを使用して2つのフィルターを作成します。

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

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

次に、フィルターグループビルダーを使用して、これら2つのフィルターで構成されるフィルターグループを構築します。

    $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);  

コールは成功しましたが、 2つの製品を受け取りました。つまり、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 /…は役に立つかもしれません。
アランケント

回答:


15

\Magento\Framework\Api\Search\FilterGroupsayの実際の注釈(phpDocクラス):

論理ORを使用して2つ以上のフィルターをグループ化します

つまり、2つのグループを作成し、それぞれに1つのフィルターを作成する必要があります。


これを明らかにしてくれてありがとう。あなただけのMagentoの2 :-Pに抽象化のすべての層を愛するようになった
Giel Berkers

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 Search Criteriaをご覧ください。


これは間違っています。ロジックは、リポジトリごとに実装されます。
アランストーム

こんにちは@Alan Storm、これはテスト済みのソリューションです。Magento 2.1.0のデフォルトストアでテストしました。それを間違って宣言する正当な理由はありますか?
カマル・シン


@アランストーム、それは私の答えで言及したものです。すべてのフィルターグループはAND演算子を使用して結合され、単一のフィルターグループのすべてのフィルターは、Magento 2の検索条件ドキュメントに従ってOR演算子を使用して結合されます。このソリューションはデフォルトストアでテストされることを述べました。あなたのコメントによると、この答えが間違っているのは、私が理解できませんでした。
カマルシン

@KamelSingh私がリンクしたバグレポートを読みましたか?かかわらず、その意図する行動の、フィルタやフィルタグループの行動は、彼らがにいるリポジトリの行動に最終的に依存している。
アランストーム
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.